如果您的记忆问题在于创建后缀树,您确定需要一个吗?您可以在一个字符串中找到所有匹配项,如下所示:
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]
我的机器很旧,运行时间为 30 秒,字符串为 4^12。我使用了一个 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。使用此代码,对于一个 4^12 长度的字符串,1000 万次搜索大约需要 13 个小时(完整搜索,零匹配,所以如果有匹配会更快)。但是,作为其中的一部分,我们需要构建 100 棵后缀树,这大约需要..100*41sec= 1 小时。
所以运行的总时间大约是 14 小时,没有内存问题……比 9.5 年有了很大的改进。请注意,我在具有 1GB RAM 的 1.6GHz CPU 上运行它,所以你应该能够做得比这更好!