メモリの問題がサフィックス ツリーの作成にある場合、サフィックス ツリーが必要ですか? 次のように、単一の文字列ですべての一致を見つけることができます。
word=get_string(4**12)+"$"
def matcher(word, match_string):
positions = [-1]
while 1:
positions.append(word.find(match_string, positions[-1] + 1))
if positions[-1] == -1:
return positions[1:-1]
print matcher(word,'AAAAAAAAAAAA')
[13331731, 13331732, 13331733]
print matcher('AACTATAAATTTACCA','AT')
[4, 8]
私のマシンはかなり古いもので、4^12 文字列で実行に 30 秒かかりました。12 桁のターゲットを使用したので、一致するものもいくつかあります。また、このソリューションは重複する結果を見つけます-ある場合。
次のようなサフィックス ツリー モジュールを試すことができます。
import suffixtree
stree = suffixtree.SuffixTree(word)
print stree.find_substring("AAAAAAAAAAAA")
残念ながら、私のマシンは遅すぎて、長い文字列でこれを適切にテストできません。しかし、おそらくサフィックスツリーが構築されると、検索は非常に高速になるため、大量の検索の場合は適切な呼び出しになるはずです。さらにfind_substring
、最初の一致のみを返します(これが問題かどうかはわかりませんが、簡単に適応できると確信しています)。
更新: 文字列を小さなサフィックス ツリーに分割して、メモリの問題を回避します。
したがって、長さ 4^12 の文字列で 1000 万回の検索を行う必要がある場合、9.5 年も待ちたくないことは明らかです (私の遅いマシンでは、標準的な単純な検索を最初に提案しました...)。ただし、サフィックス ツリーを引き続き使用することができ (したがって、はるかに高速になります)、メモリの問題を回避できます。大きな文字列を扱いやすいチャンクに分割し (マシンのメモリが処理できることがわかっています)、チャンクをサフィックス ツリーに変換し、1000 万回検索してから、そのチャンクを破棄して次のチャンクに移動します。また、各チャンク間のオーバーラップを検索することも忘れないでください。これを行うためのコードをいくつか書きました (検索される大きな文字列word
は、管理可能な最大文字列長の倍数であると想定してmax_length
います。場合):
def split_find(word,search_words,max_length):
number_sub_trees = len(word)/max_length
matches = {}
for i in xrange(0,number_sub_trees):
stree = suffixtree.SuffixTree(word[max_length*i:max_length*(i+1)])
for search in search_words:
if search not in matches:
match = stree.find_substring(search)
if match > -1:
matches[search] = match + max_length*i,i
if i < number_sub_trees:
match = word[max_length*(i+1) - len(search):max_length*(i+1) + len(search)].find(search)
if match > -1:
matches[search] = match + max_length*i,i
return matches
word=get_string(4**12)
search_words = ['AAAAAAAAAAAAAAAA'] #list of all words to find matches for
max_length = 4**10 #as large as your machine can cope with (multiple of word)
print split_find(word,search_words,max_length)
この例では、サフィックス ツリーの最大長を 4^10 に制限しており、これには約 700MB が必要です。このコードを使用すると、1 つの 4^12 の長さの文字列に対して、1,000 万件の検索に約 13 時間かかります (完全な検索で、一致するものがないため、一致する場合はより速くなります)。ただし、その一環として、100 個のサフィックス ツリーを構築する必要があり、約 100*41 秒 = 1 時間かかります。
したがって、合計実行時間は約 14 時間で、メモリの問題はありません... 9.5 年から大幅に改善されました。私はこれを 1GB の RAM を搭載した 1.6GHz の CPU で実行していることに注意してください。