私はこの質問に答えるのに少し遅れていますZ-Algorithm
が、対応するものよりもはるかに速いと思います。最悪の場合の複雑さはO(m + n)であり、パターン/テキストの前処理を必要としません。他のアルゴリズムと比較して、コーディングも非常に簡単です。
次のように機能します。
たとえば、文字列がありますS ='abaaba'
。のz(i)
値を見つけますi=0 to len(S)-1
。説明に入る前に、最初にいくつかの定義を置いておきます。
z(i)
=いいえ。のプレフィックスの文字のうち、のプレフィックスS
と一致するものs(i)
。
s(i)
=のith
接尾辞S
。
以下はのs(i)
値ですs = 'abaaba'
。
s(0) = 'abaaba' = S
s(1) = 'baaba'
s(2) = 'aaba'
s(3) = 'aba'
s(4) = 'ba'
s(5) = 'a'
z値はそれぞれ
z(0) = 6 = length(S)
z(1) = 0
z(2) = 1
z(3) = 3
z(4) = 0
z(5) = 1
アルゴリズムの詳細については、次のリンクを参照してください。
http://codeforces.com/blog/entry/3107
https://www.youtube.com/watch?v=MFK0WYeVEag
今、すべてを見つけるにはO(N)が必要です z
、前処理のオーバーヘッドなしで値です。このロジックを使用して特定の文字列のパターンをどのように一致させることができるのでしょうか?
例を見てみましょう。パターン(P):aba
テキスト(T): aacbabcabaad
。
これをP $ Tの形式で入力します。($
-パターンまたはテキストのどちらにも表示されない文字。$
しばらくして重要性が出てきます。)
P$T
= aba$aacbabcabaad
知ってる len(P)
= 3。
のすべてのz値P$T
は
z(0) = 16 = len(P$T)
z(1) = 0
z(2) = 1
z(3) = 0
z(4) = 1
z(5) = 1
z(6) = 0
z(7) = 0
z(8) = 2
z(9) = 0
z(10) = 0
z(11) = 3
z(12) = 0
z(13) = 1
Z(14) = 1
Z(15) = 0
さて、これはz(i)
= len(P)
です。Ans = 11.
したがって、パターンはAns-len(P)-1
=に存在し7
ます。-1
のためです$
キャラクターです。
さて、なぜか$
そのような特殊文字が重要です。考えてみましょうP = 'aaa'
とT = 'aaaaaaa'
。特殊文字がないz(i)
と、すべてに増分値があります。以下の式を使用して、テキスト内のパターンの位置を見つけることができます。
条件:z(i)
> = len(P)
および位置:Ans-len(P)
。ただし、この場合の状態は少し複雑でわかりにくいものになります。私は個人的に特殊なキャラクターのテクニックを使うことを好みます。