高速k不一致文字列マッチングアルゴリズム


10

高速なk不一致文字列マッチングアルゴリズムを探しています。長さmのパターン文字列Pと長さnのテキスト文字列Tが与えられた場合、Pが最大でk個の不一致を持つTの部分文字列と一致するすべての位置を見つけるための高速(線形時間)アルゴリズムが必要です。これは、k差問題(編集距離)とは異なります。不一致は、部分文字列とパターンの最大k個の位置に異なる文字があることを意味します。本当に必要なのはk = 1(最大で1つの不一致)だけなので、k = 1の特定のケースに対する高速アルゴリズムでも十分です。アルファベットのサイズは26(大文字と小文字を区別しない英語のテキスト)であるため、スペースの要件はアルファベットのサイズに比例して大きくなりすぎないようにする必要があります(たとえば、FAASTアルゴリズムは、アルファベットのサイズで指数関数的にスペースを取るなど)。タンパク質および遺伝子配列にのみ適しています)。

ダイナミックプログラミングベースのアプローチは、最悪の場合O(mn)になる傾向があり、遅くなります。私はこのためのボイヤー・ムーアアルゴリズムの変更があると信じていますが、私はそのような論文を手に入れることができません。私は学術雑誌や出版物にアクセスするためのサブスクリプションを持っていないので、すべての参照はパブリックドメインにある必要があります。

私は、ポインタ、または自由に入手できるドキュメントへの参照、またはこの問題のアルゴリズム自体に大いに感謝します。


2
パターンが固定されている場合(ただし、一致するテキストはさまざまです)、有限オートマトンを作成し、それを介してテキストを実行することができます。接尾辞ツリーを使用するアルゴリズムもあります(通常、テキストが一定でパターンが異なる場合に適していますが、両方が異なる場合にも適用できます)。Webでいくつかの参照を見つけることができる場合があります。(サフィックスツリーベースのアルゴリズムについてはよくわからないため、まだ回答を追加していません。誰かが知っている場合は、このコメントを無視してください)。
Aryabhata

@Aryabhataありがとう!パターンとテキストの両方が変化します。そのコンテキストでは、有限オートマトンの構築は、特に1つの不一致のスコープを含める場合、非常にコストがかかります。suffix trees / suffix arrayについては、私はそれらを使用したことがなく、それらについてほとんど知りませんが、構築が遅く、主に完全一致に対して効率的であるという印象を受けました。しかし、私はこのオプションをさらに探求します。この方向、または他の方向のポインタが最も役立ちます。
Paresh 2012

1
いいえ、接尾辞ツリーはおおよその一致にも使用できます。少なくともwikiはそう主張しています:en.wikipedia.org/wiki/Suffix_tree
Aryabhata

回答:


5

この問題には、接尾辞配列を使用できます。それらには、辞書式順序でソートされたストリングの各サフィックスの開始位置が含まれています。それらは単純に複雑度で構築できますが、Θ n )の複雑度で構築する方法があります。たとえばthisthisを参照してください。このサフィックス配列をSAと呼びます。O(nlogn)Θ(n)

サフィックス配列が作成されたら、サフィックス配列の最長共通プレフィックス(LCP)配列を作成する必要があります。LCP配列は、接尾辞配列内の2つの連続する接頭辞の間の最も長い共通の接頭辞の長さを格納します(辞書式の連続する接尾辞)。したがって、LCP [i]には、SA [i]とSA [i + 1]の間の共通の最長プレフィックスの長さが含まれています。この配列は、線形時間で構築することもできます。いくつかの優れたリファレンスについてここここ、およびここを参照してください。

uvu<vminu<=k<=v1LCP[k]LCPO(n)O(nlogn)LCP[u,v]O(1)

iTLCPTiPPT[i]l0TPLCPT[i+l0+1]P[l0+1]kLCPO(1)O(k) LCPiTO(nk)

O(nk+(n+m)log(n+m))O(nk+nlogn)m=O(n)O(nk)


すごい!TODOリストを読んでいます:-)
Aryabhata

2番目の段落のsiam.orgリンクは壊れていますが、リンクされた論文はここにありますepubs.siam.org/doi/pdf/10.1137/1.9781611972917.3
leecbaker

4

O(n+m)kO(nk+m)

この考え方は、部分文字列を完全に一致させるためのRabin-Karpローリングハッシュアルゴリズムに似ています。

m2km/2k2k2k

k

k

私は期待します(警告:自分で試したことがありません)。これは、サフィックスツリーベースのアプローチを使用するよりも、実際にはおそらく高速で、おそらくコーディング/保守が簡単です。


ただ明確にする必要があります。「長さmの各文字列をそれぞれm / 2kサイズの2kブロックに分割する...」とは、Tの長さnのmの各部分文字列を2kブロックに分割することを意味します。そして、このハッシュは、ローリングハッシュ法によってO(n)で計算できます。次に、パターン文字列も2k個のブロックに分割され、対応するハッシュが比較されて、最大でk個のブロックの不一致が許容されます。その場合、不一致の数がkを超えるすべてのケースを破棄できる可能性があります。分かりましたか?
Paresh 2012

kΩ(nk)O(n)

私はこのアプローチが好きです!しかし、このアプローチは一般的に高速ですが、一致数が多い場合はO(mnk)に低下します(O(n)一致)。これを念頭に置いて、2つのローリングハッシュを維持しました。両方とも同じ入力に対して衝突することはできないという前提の下で(速度を確認したかったので、数学的にこれを行いませんでした)。このようにして、2つのハッシュが一致する場合、一致する文字を検証する必要がありません。これは一般にかなり高速ですが、一致の数が多い場合も低速です。これとあなたが提案した方法では、大規模な試合では時間がかかりました。
Paresh、2012年

これを最悪の場合、テキストを分割すると、より速くなる可能性があります。mm/2kmO(nkm)

mm/2k2kk+1k+cΩ(nm)mm/2k
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.