web-dev-qa-db-ja.com

いつKMPoverBOYER-MOOREを使用しますか

私は現在、パターンマッチングアルゴリズムについて学習しており、これら2つのアルゴリズムに出くわしました。私は次の一般的な考えを持っています:

KMP

  • テキストを左から右に比較します
  • 障害配列を使用してインテリジェントにシフトします
  • 故障配列を計算するために、O(m)(mはパターンの長さ)を取ります
  • o(m)、スペースを取る
  • 文字列を検索するのにO(n)、時間がかかります

BM

  • 最後の文字のパターンを比較します
  • 悪い文字ジャンプと良い接尾辞ジャンプを使用します
  • テーブルを計算するためにO(m +アルファベットのサイズ)を取ります
  • o(m +アルファベットのサイズ)、スペースを取る
  • o(n)を取りますが、通常は検索する方が良いです

私はこの質問を引き起こした次の質問に出くわしました(TrueまたはFalse):

Knuth-Morris-Pratt(KMP)アルゴリズムは、多くの異なるテキストで同じパターンを繰り返し検索する場合に適しています。

したがって、異なるテキストでアルゴリズムを実行するたびに前処理がO(n)であるという前提があるため、答えは正しいと思います。ここで、BMの場合はO(n +サイズただし、アルゴリズムが再実行されるたびに新しいテーブルが再計算されるという正しい仮定をしているのかどうかはわかりません。テキストは常に英語のアルファベットであるため、テーブルを計算する必要があるのは1回だけです。結局のところ、この質問への答えは、アルゴリズムがすべて同じアルファベットに含まれるテキストで実行されているという事実、または影響を与える可能性のある他の要因があるという事実に依存しますか?それ?

24
Eric

理論的には、両方のアルゴリズムのパフォーマンスは「類似」します。 KMPは検索フェーズで約2nの比較を行い、Boyer-Mooreは検索フェーズで約3nの比較を行います最悪の場合。どちらの場合も、新しいテキストを取得するときに前処理を繰り返す必要はありません。

しかし、本当の答えは、実際にはどちらも使用すべきではないということです。

両方のアルゴリズムに必要な線形補助ストレージは、すべての余分なメモリアクセスのために、最新のアーキテクチャでかなり...より粗いパフォーマンスにつながります。

ただし、ボイヤームーア文字とKMPの背後にあるideasは、最も高速な文字列照合アルゴリズムを支えています。 KMPの「失敗関数」のアイデアのようなものは、私が知っているすべての実用的に効果的な文字列照合アルゴリズムで使用されています。パターンの次善の「失敗関数」をオンザフライで計算できることがわかりました。これにより、一定の追加スペースのみが必要でありながら、線形の時間マッチングが可能になります。ボイヤームーア文字は、固定パターンをランダムノイズと照合する「平均的な場合」では線形よりも高速であり、これは多くの実際の状況で有効です。

22
tmyklebu