Wordの提案を伴うスペルチェッカーを実装するときに通常使用されるアルゴリズムは何ですか?
最初に、(辞書に見つからない場合は)入力された新しいWordを辞書内の他のすべてのWordからの Levenshtein distance に対してチェックし、上位の結果を返すことは理にかなっていると思いました。ただし、これは非常に効率が悪く、辞書全体を繰り返し評価する必要があるようです。
これは通常どのように行われますか?
Peter Norvigによる優れたエッセイ スペルコレクターの実装方法があります。基本的には、与えられた編集距離で候補文字列を試すブルートフォースアプローチです。 ( ここ は ブルームフィルター および 高速候補ハッシュ を使用してスペル修正プログラムのパフォーマンスを向上させるためのヒントです。)
スペルチェッカーの要件はより弱くなります。 Wordが辞書にないことを知るだけです。 Bloom Filter を使用して、メモリの消費量が少ないスペルチェッカーを構築できます。古代のバージョンは Programming Pearls で英語の辞書に64kbを使用してJon Bentleyによって記述されています。
BK-Tree は代替アプローチです。素敵な記事は こちら です。
レーベンシュシュタインの距離は、スペルチェッカーの正確な編集距離ではありません。挿入、削除、および置換のみを知っています。転置が欠落しており、1文字の転置に対して2が生成されます(1削除および1挿入)。 Damerau–Levenshtein distance は正しい編集距離です。
私が首尾よく使用したがどこにも記述されていない提案を生成するアプローチは、「悪い」ハッシュ関数を使用して提案を事前に計算することです(辞書を構築するとき)。
アイデアは、人々が犯すスペルミスのタイプを調べ、正しいスペルと同じバケットに誤ったスペルを割り当てるハッシュ関数を設計することです。
たとえば、よくある間違いは、definiteの代わりにdefinateのような間違った母音を使用することです。したがって、すべての母音を同じ文字として扱うハッシュ関数を設計します。それを行う簡単な方法は、最初に入力Wordを「正規化」してから、正規化された結果を通常のハッシュ関数に入力することです。この例では、正規化関数はすべての母音を削除する可能性があるため、definite
はdfnt
になります。次に、「正規化された」Wordは、典型的なハッシュ関数でハッシュされます。
この特別なハッシュ関数を使用して、すべての辞書の単語を補助インデックス(ハッシュテーブル)に挿入します。このテーブルのバケットには、ハッシュ関数が「不良」であるため、衝突リストが長くなりますが、これらの衝突リストは基本的に事前計算済みの提案です。
これで、スペルミスのあるWordを見つけると、補助インデックスでスペルミスのマッピング先のバケットの衝突リストを検索します。 Ta da:提案リストがあります!あなたがしなければならないのは、その上の単語をランク付けすることです。
実際には、他のタイプのエラー(転置文字、シングル/ダブルレター、さらには発音のミススペルをキャッチするための単純なSoundexのようなエラー)を処理するために、他のハッシュ関数を備えたいくつかの補助インデックスが必要です。実際、私は単純な発音のものは長い道のりを歩み、些細なタイプミスを見つけるために設計されたもののいくつかを本質的に廃止しました。
したがって、各補助インデックスのスペルミスを検索し、ランキングの前に衝突リストを連結します。
コリジョンリストには、辞書にある単語のみが含まれていることに注意してください。 (Peter Norvigの記事のように)別のスペルを生成しようとするアプローチでは、最初に辞書に対してフィルター処理する必要がある(数万)候補を取得できます。事前に計算されたアプローチでは、おそらく数百の候補者が得られ、それらはすべて正しいスペルであることがわかっているので、ランキングにすぐにスキップできます。
Update:以来、これに似たアルゴリズムの説明を1つ見つけました FAROO Distributed Search 。これはまだ編集距離に制限のある検索ですが、事前計算ステップは私の「悪いハッシュ関数」のアイデアのように機能するため、非常に高速です。 FAROOは、不正なハッシュ関数という限られた概念を使用しています。
辞書内の各単語の正確な編集距離を知る必要はありません。制限値に達した後にアルゴリズムを停止し、Wordを除外できます。これにより、計算時間を大幅に節約できます。