3

最近、レーベンシュタイン距離を計算するためのアルゴリズムの最適化に関する質問を投稿しました。その回答から、レーベンシュタイン距離に関するWikipediaの記事が表示されます。

この記事では、最大距離に限界kがある場合、与えられたクエリから可能な結果が得られる可能性があると述べています。実行時間はO(mn)からO(kn)に短縮できます。mnはの長さです。文字列。アルゴリズムを調べましたが、実装方法がわかりませんでした。私はここでそれについていくつかのリードを得ることを望んでいました。

最適化は「可能な改善」の#4です。

私を混乱させたのは、主対角線を中心とした幅2k + 1の対角線ストライプを計算するだけでよいと言った部分です(主対角線は座標(i、i)として定義されます)。

誰かが助け/洞察を提供することができれば、私は本当にそれをいただければ幸いです。必要に応じて、アルゴリズムの完全な説明を本の回答としてここに投稿できます。

4

1 に答える 1

3

私はそれを何度もやりました。私がそれを行う方法は、可能な変更のゲームツリーの再帰的な深さ優先ツリーウォークです。私が木を剪定するために使用する変更の予算kがあります。そのルーチンを手にした状態で、最初にk = 0、次にk = 1、次にk = 2で実行し、ヒットするか、それ以上は行きたくないようにします。

char* a = /* string 1 */;
char* b = /* string 2 */;
int na = strlen(a);
int nb = strlen(b);
bool walk(int ia, int ib, int k){
  /* if the budget is exhausted, prune the search */
  if (k < 0) return false;
  /* if at end of both strings we have a match */
  if (ia == na && ib == nb) return true;
  /* if the first characters match, continue walking with no reduction in budget */
  if (ia < na && ib < nb && a[ia] == b[ib] && walk(ia+1, ib+1, k)) return true;
  /* if the first characters don't match, assume there is a 1-character replacement */
  if (ia < na && ib < nb && a[ia] != b[ib] && walk(ia+1, ib+1, k-1)) return true;
  /* try assuming there is an extra character in a */
  if (ia < na && walk(ia+1, ib, k-1)) return true;
  /* try assuming there is an extra character in b */
  if (ib < nb && walk(ia, ib+1, k-1)) return true;
  /* if none of those worked, I give up */
  return false;
}

トライ検索を説明するために追加されました:

// definition of trie-node:
struct TNode {
  TNode* pa[128]; // for each possible character, pointer to subnode
};

// simple trie-walk of a node
// key is the input word, answer is the output word,
// i is the character position, and hdis is the hamming distance.
void walk(TNode* p, char key[], char answer[], int i, int hdis){
  // If this is the end of a word in the trie, it is marked as
  // having something non-null under the '\0' entry of the trie.
  if (p->pa[0] != null){
    if (key[i] == '\0') printf("answer = %s, hdis = %d\n", answer, hdis);
  }
  // for every actual subnode of the trie
  for(char c = 1; c < 128; c++){
    // if it is a real subnode
    if (p->pa[c] != null){
      // keep track of the answer word represented by the trie
      answer[i] = c; answer[i+1] = '\0';
      // and walk that subnode
      // If the answer disagrees with the key, increment the hamming distance
      walk(p->pa[c], key, answer, i+1, (answer[i]==key[i] ? hdis : hdis+1));
    }
  }
}
// Note: you have to edit this to handle short keys.
// Simplest is to just append a lot of '\0' bytes to the key.

さて、それを予算に制限するために、hdisが大きすぎる場合は下降を拒否してください。

于 2010-07-07T15:47:54.367 に答える