如果您在创建后缀树时遇到了内存问题,您确定需要创建一个后缀树吗?您可以通过以下方式在单个字符串中查找所有匹配项:
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']
max_length = 4**10
print split_find(word,search_words,max_length)
在这个例子中,我将最大后缀树长度限制为4^10长度,需要大约700MB的空间。使用此代码,对于一个长度为4^12的字符串,1000万次搜索应该需要大约13小时(完全搜索,没有匹配项,所以如果有匹配项,速度会更快)。但是,作为其中的一部分,我们需要构建100棵后缀树,这将需要大约...100*41秒=1小时。
因此,总运行时间约为14小时,没有内存问题......比9.5年的时间有了很大的改进。请注意,我在1.6GHz CPU和1GB RAM上运行此代码,所以您应该能够做得比这更好!