n個の文字列が与えられた場合、それらの1つは別の部分文字列ですか?


9

n文字列のコレクションが与えられたとしますS1,,Sn。これらの文字列のいずれかがコレクション内の他の文字列の部分文字列であるかどうかを知りたいのですが。つまり、次のタスクのアルゴリズムが必要です。

入力:S1,,Sn

出力:i,jようなSiの部分文字列であるSjij、またはNoneがない場合は、このようなi,jが存在

これのための効率的なアルゴリズムはありますか?

「部分文字列」を「接頭辞」で置き換える場合、効率的なアルゴリズムがあります(文字列を並べ替えてから、線形スキャンを実行して隣接する文字列を比較します。並べ替えにより、部分文字列が確実に隣接します)。しかし、文字列が他の文字列の部分文字列であるかどうかをテストすることは、より困難に思えます。単純なアルゴリズムは、すべてのペアを反復処理することですが、これにはΘ n 2サブストリングテストが必要です。より効率的なアルゴリズムはありますか?i,jΘ(n2)

これを「すべてのペアの部分文字列テスト」などと呼ぶことができると思います。

私の最終的な目標は、コレクション内の何かの部分文字列である各文字列を削除することにより、コレクションをプルーニングして文字列が他の文字列の部分文字列にならないようにすることです。


ヒント:サフィックス配列。
仮名2014年

補足として、は、部分文字列を見つけたときにそれらを削除すると正しくありません。少なくなります。また、長い文字列は短い文字列では表示できないため、長さで並べ替える必要があります。ここでもΘ n 2は間違っています。Θ(n2)Θ(n2)
Alexis Wilke 2014年

@AlexisWilke、は正解です。これは、最悪の場合の部分文字列テストの数です(最悪の場合は、文字列が他のどの部分文字列でもない場合です)。長さによるソートでは2の因数しか得られませんが、漸近には影響しません。Θ(n2)
DW

回答:


6

線形時間でサフィックスツリーを構築し、完全な文字列(ノードごとの一定時間)に対応する内部ノードがあるかどうかを確認できます。

より詳細には、我々は、文字列与えられていると仮定しs1,,snΣ

  1. (一般)構築接尾辞木nは異なる端末マーカーを対毎$ 1... $ NΣs1$1,s2$2,,sn$nn$1,,$nΣ

    ウッコネンのアルゴリズムを使用すると、これは線形時間で実行できます。すべての文字列の長さの合計で線形。

  2. 葉が接尾辞s i [ jを表す場合葉にラベルを付けると仮定します| s i | ] of s iは、ツリーを走査して、i 0 というラベルが付いたn個の葉、つまり、完全な文字列に対応する葉を見つけます。(i,j)si[j..|si|]sin(i,0)

    これは、ツリーサイズで線形に時間がかかります。ツリー自体は入力サイズで線形です。

  3. の親の子孫の葉$ iとラベル付けされたエッジが到達する)は、セットからのすべての一致を表します。これは、接尾辞ツリーの基本的な不変式によるものです。葉に降順で一致するものを見つけます(ただしi 0 )。(i,0)$i(i,0)

    これにも線形時間がかかります。

明確な端末マーカーは実際には必要ありません。リーフごとに複数のラベルを許可する限り、すべての文字列を終了するために使用される1つで十分です。

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