web-dev-qa-db-ja.com

2つの文字列に一致しますが、ある程度のエラーを許容します

どうすれば2つの文字列を一致させることができますが、同時に、一致するX個の文字が正しくない場合があります。エラー数は制御可能な変数である必要があります。

X個の文字は文字列内で一致することはできませんが、シーケンスで実行される文字数には制限があります。 2つの文字列が与えられた場合、5文字が異なることを許可する場合がありますが、連続して2文字を超えることはできません。

私はこれらの2つの文字列を比較するための推奨アルゴリズムを探しています。または、これに対する既知の解決策がすでにあるかもしれません。

10
Reactgular

おおよその文字列検索の開始点は、 Levenshtein distance の開始点です。このアルゴリズムは、1つのWordを別のWordに変更するための単一文字の編集(挿入、削除、および置換)の数をカウントします。

この例はkitten-> sittingで、編集距離は3です。

  1. kイッテン-> sitten( 'k'を 's'に置き換えます)
  2. シットen->シットn (substitute 'i' for 'e')
  3. シッティン->シッティンg (最後に「g」を追加)

このアルゴリズムにはバリエーションがあり、特に Damerau–Levenshtein distance は、2つの隣接する文字の転置を可能にします( 'hte'から 'the'にはDL距離がありますが1で、レーベンシュタイン距離が2)であるため、スペルチェックに適している場合が多いです。

レーベンシュタイン距離はよく知られており、見つけるのはそれほど難しくありません(以前は、その実装を Oracleの関数 として探す必要がありましたが、すべてのデータをプルダウンして実行するよりもはるかに高速でしたクエリコード側)。 Rosettacodeには Levenshtein distance の実装が多数(54)あります(一部の言語ではこれが文字列ライブラリの一部としてどこかにあることに注意してください-Javaを使用している場合は Apache commons lang )。 Wikibooks には31の実装があり、2つをざっと見ただけでは同じ言語の同じコードが表示されません。

これが機能する方法は、2つの文字列間の関係に対応する行列を作成することです。

_ .kitten
.0123456
s1123456
i2212345
t3321234
t4432123
i5543223
n6654332
g7765443
_

_._の行と列は、空の文字列から各文字を「単に」挿入するだけでターゲット文字列に到達できることを表しています。これは理想的なケースではありませんが、アルゴリズムをシードするためにあります。

値がそのスポットと同じ場合( 'i' == 'i')、値は左斜め上方向の値と同じです。 2つのスポットが異なる場合( 's'!= 'k')、値は最小値です。

  • 上斜め左+ 1(置換)
  • + 1の真上(挿入)
  • すぐ左+ 1(削除)

編集距離の戻り値は、マトリックスの右下にある値です。

右下から左上に最小値で進むと、編集が完了したことがわかります。

_ .kitten
.0.   .
s.1   .
i  1  .
t   1 .
t    1.
i.....2
n      2
g......3
_

これはかなりメモリ集約的なアプローチであることに注意してください。完全な行列を構築しないことで、メモリスコープを減らすことができます-アルゴリズムのすべてがデータのサブセットであり、_N*M_スペースから2*max(N,M)スペースに減らすだけで、前の行(および現在の行で計算されたもの)。 Code Project は、これを行う方法を示しています(ダウンロードするC#コードを使用)。

12
user40980