PythonKPMアルゴリズム

ナレッジポイントの説明:

最初に接頭辞と接尾辞について話しましょう。

たとえば、次の文字列があります:abab

その場合、下付き文字は3になります(接頭辞と接尾辞は両方とも下付き文字の長さより1短く、下付き文字は3で、長さは4です)

プレフィックスは次のとおりです:a、ab、aba

接尾辞は次のとおりです:b、ba、bab

1.KPMアルゴリズムのnext[]配列を取得するには

原理について簡単に説明します。まず、kを使用してプレフィックスの添え字を格納します。まず、j = 0を初期化します(jはパターン文字列の添え字を表すために使用します。常にパターン文字列の各ビットを前のビットと比較します。 1.等しい場合は、現在の位置が前の位置と同じである位置を記録します。主に同じ位置の次の位置、つまり同じ位置を記録します。比較のために同じ位置から開始するのはバックトラックです。同じ位置にあるので、ここtで[j] == t [k]が確立されると、j + 1が必要になります。次の位置が同じかどうかを比較するために、kも+1)、パターン文字列0から始まり、k = -1、next [0]=-1最初の位置にはデフォルト値-1が割り当てられます。

ここで、文字列は="abab"を使用します

最初のループ:

kが-1に等しいかどうかを判断します。等しい場合は、jとkの両方が+1です。

このとき、j = 1、k = 0、next [1] = 0、つまり、プレフィックスの最大長が長さよりも短くなければならないため、2番目の位置(添え字1)のバックトラッキング位置は0のままです。現在の位置の;

2番目のサイクル:

j = 1、k = 0、next [1] = 0; kは-1に等しくない、t [j] == t [k]、t [1] == t [0]、t[1]と判断する= "b"、t [0] = "a"、等しくない

elseを実行します。

k = next [0] =-1

3番目のサイクル:

k ==-1

jとkは両方とも+1、j = 2、k = 0、next [2]=0です

4番目のサイクル:

kは-1に等しくなく、t [2] == t [0]、t [2] =“ a” = t [0] =“ a”と判断され、確立されます

jとkは両方とも+1、j = 3、k = 1、next [3]=1です

このとき、next = [-1,0,0,1]、next [3] = 1は、next [3]で不一致が発生した場合、つまりパターン文字列の添え字が3の場合、「 b "、前のaba Allがターゲット文字列と一致することを示します。したがって、パターン文字列の一致しない位置の前の文字列abaは、ターゲット文字列の一致しない位置の前の最初の3つの値と等しくなければなりません。はabaなので、現時点では、パターン文字列の1の位置に戻るだけで済みます。つまり、パターン文字列のb、パターン文字列bの前にaがあり、ターゲット文字列の前のaは次のようになります。満足。

5番目のサイクル:

kはまだ-1に等しくありません。つまり、前の位置の後の2つの数値を比較してから、それらを比較します。簡単に言えば、各項目を取り出して最初の項目と比較します。等しいものがある場合は、次のものと2番目のもの。アイテムは等しい。

コードは次のように表示されます。

def GetNext(t, next):
    j, k = 0, -1
    next[0] = -1
    while j < len(t) - 1:
        if k == -1 or t[j] == t[k]:  # 如果k==-1 或者 开始位置和结尾位置有相同的元素
            j, k = j + 1, k + 1  # j和k都加1,当前位匹配,则从下一个位置开始匹配,所以k+1;j再进行取下一位判断是否也是匹配,所以也要+1
            next[j] = k  # 当前位置要取k项
        else:#如果不相等,再把k置-1,下一次循环再进行+1操作,j这个位置再存入0,表示无匹配项
            k = next[k]
    return next

2.KMP機能

原理はBFアルゴリズムと同じですが、唯一の違いは、パターン文字列がターゲット文字列と一致しない場合、パターン文字列は直接バックトラックされませんが、バックトラックされる位置は次の[]テーブルに従ってクエリされることです。パターン文字列、パターン文字列の指定された位置に直接バックトラックする、KMPアルゴリズムのコアはここにありますが、この方法は通常、プレフィックスとサフィックスに同じ要素がある場合、つまり同じ場合にのみ有効です。部分は同じであり、もう比較されません。比較は同じ要素の次の位置から開始されるため、KMPアルゴリズムの最も複雑な部分は、実際にはnext []テーブルを見つけて、パターン文字列のプレフィックスは同じです。その場合は、同じ位置をマークします。次回、バックトラックで0の位置にバックトラックする必要がない場合は、別の位置から開始できます。

def KMP(s, t):
    next = [0] * len(t)
    next = GetNext(t, next)
    print(next)
    i, j = 0, 0
    while i < len(s) and j < len(t):
        if j == -1 or s[i] == t[j]:
            i, j = i + 1, j + 1
        else:
            j = next[j]
    if j >= len(t):
        return i - len(t)
    else:
        return -1

完全なコード:

def GetNext(t, next):
    j, k = 0, -1
    next[0] = -1
    while j < len(t) - 1:
        if k == -1 or t[j] == t[k]:  # 如果k==-1 或者 开始位置和结尾位置有相同的元素
            j, k = j + 1, k + 1  # j和k都加1,当前位匹配,则从下一个位置开始匹配,所以k+1;j再进行取下一位判断是否也是匹配,所以也要+1
            next[j] = k  # 当前位置要取k项
        else:#如果不相等,再把k置-1,下一次循环再进行+1操作,j这个位置再存入0,表示无匹配项
            k = next[k]
    return next


def KMP(s, t):
    next = [0] * len(t)
    next = GetNext(t, next)
    print(next)
    i, j = 0, 0
    while i < len(s) and j < len(t):
        if j == -1 or s[i] == t[j]:
            i, j = i + 1, j + 1
        else:
            j = next[j]
    if j >= len(t):
        return i - len(t)
    else:
        return -1


if __name__ == '__main__':
    re = KMP('asdfghjsssaaasdfaaaabababcdabd', "ababaaaababaa")
    print(re)

結果:

 

おすすめ

転載: blog.csdn.net/baidu_39105563/article/details/121754173