web-dev-qa-db-ja.com

ボイヤームーアアルゴリズムの理解と例?

ボイヤームーアの文字列検索アルゴリズムを理解する際に問題に直面しています。

次のドキュメントをフォローしています。 リンク

ここでdelta1とdelta2の本当の意味は何なのか、そしてこれを文字列検索アルゴリズムを見つけるためにどのように適用するのかを正確に判断することはできません。言語は少しあいまいに見えました。

誰かがこれを理解するのを手伝ってくれるなら、それは本当に役に立ちます。

または、理解しやすい他の利用可能なリンクまたはドキュメントを知っている場合は、共有してください。

前もって感謝します。

31
AGeek

アドバイスの最初の部分は、深呼吸してください。あなたは明らかにストレスを感じており、ストレスがかかったときに最初に起こるのは、脳の大きな塊がシャットダウンすることです。これにより、理解が難しくなり、ストレスが増加し、問題が発生します。

ヘッドスペースを改善するための5分間のタイムアウトをとることは不可能に思えるかもしれませんが、驚くほど役立ちます。

さて、このアルゴリズムは単純な原理に基づいています。長さmの部分文字列と一致させようとしているとします。最初にインデックスmの文字を見ていきます。その文字が文字列にない場合、必要な部分文字列はインデックス1, 2, ... , m

その文字が私の文字列にある場合、それが可能な文字列の最後の場所にあると仮定します。次に、ジャンプして、可能な開始位置から文字列を一致させようとします。この情報は私の最初の表です。

部分文字列の先頭から一致を開始し、不一致を見つけた場合、ゼロから開始することはできません。別のポイントから始まる試合に部分的に参加することもできます。たとえば、anandananandを一致させようとしている場合、ananは、次のadではないことを認識しますが、anと一致しているので、3番目の文字と一致するようにジャンプする必要があります部分文字列。これは、「x文字のマッチング後に失敗した場合、マッチのy番目の文字になる可能性がある」という情報が2番目のテーブルに格納されます。

マッチに失敗した場合、2番目のテーブルはマッチの距離を知っていることに注意してください。最初の表は、私が見たキャラクターのうち、一致しなかったものに基づいて、どれくらい前に戻るかを知っています。これらの2つの情報をより悲観的に使用する必要があります。

これを念頭に置いて、アルゴリズムは次のように機能します。

start at beginning of string
start at beginning of match
while not at the end of the string:
    if match_position is 0:
        Jump ahead m characters
        Look at character, jump back based on table 1
        If match the first character:
            advance match position
        advance string position
    else if I match:
        if I reached the end of the match:
           FOUND MATCH - return
        else:
           advance string position and match position.
    else:
        pos1 = table1[ character I failed to match ]
        pos2 = table2[ how far into the match I am ]
        if pos1 < pos2:
            jump back pos1 in string
            set match position at beginning
        else:
            set match position to pos2
FAILED TO MATCH
46
btilly

Boyer-Mooreの背後にある洞察は、パターン内のlast文字で始まる文字列内のパターンの検索を開始すると、不一致に遭遇したときに複数の文字を前方に検索できることです。

パターンpが文字シーケンスp1p2、...、pnであり、現在sppnのインデックスiにあるように整列された文字列sを検索しているとします。

例えば。:

s = WHICH FINALLY HALTS.  AT THAT POINT...
p = AT THAT
i =       ^

B-Mペーパーは、次の観察を行います。

(1)pにない文字と一致させようとすると、n文字を前方にジャンプできます。

「F」はpにないため、n文字を進めます。

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =        AT THAT
i =              ^

(2)最後の位置がkの最後からpである文字と一致させようとすると、k文字を前方にジャンプできます。

pの 'の最後の位置は末尾から4なので、4文字進めます。

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =            AT THAT
i =                  ^

ここで、成功するか不一致が見つかるまで、iから逆方向にスキャンします。 (3a)kの最初からp文字が一致し、一致しない文字がpにない場合、(少なくとも)k文字を進めることができます。

「L」はpになく、p6に対して不一致が発生したため、6文字以上進めることができます:

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =                  AT THAT
i =                        ^

しかし、実際にはこれよりもうまくやることができます。 (3b)古いiですでにいくつかの文字(この場合は1)と一致していることがわかっているため。一致した文字がpの先頭と一致しない場合、実際にはもう少し先にジャンプできます(この余分な距離は、論文では「delta2」と呼ばれます)。

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =                   AT THAT
i =                         ^

この時点で、観測(2)が再び適用され、

s = WHICH FINALLY HALTS.  AT THAT POINT...
p =                       AT THAT
i =                             ^

ビンゴ!終わったね。

113
Rafe