更复杂但速度更快:将字符串列表预处理为前缀树。
然后,对于每个文件行,在每个字符位置开始,看看你能走多远进入前缀树。
如果你保持所有活动前缀树的队列,你只需要在扫描行时查看每个字符位置一次。你还可以在每个前缀树节点处包括一个“最小终端深度”计数器,以便在接近字符串结尾时尽早截断比较。
一个更简单的方法是将你的字符串大列表转换成一个字典,其中每个键都是你要查找的字符串的前三个字符,对应的值则是包含这些字符串的列表。
from itertools import count, tee, izip
def triwise(iterable):
"s -> (s0,s1,s2), (s1,s2,s3), (s2,s3,s4), ..."
a, b, c = tee(iterable, 3)
next(b, None)
next(c, None)
next(c, None)
return izip(a, b, c)
class Searcher:
def __init__(self):
self.index = {}
def add_seek_strings(self, strings):
for s in strings:
pre = s[:3]
if pre in self.index:
self.index[pre].append(s)
else:
self.index[pre] = [s]
def find_matches(self, target):
offset = -1
for a,b,c in triwise(target):
offset += 1
pre = a+b+c
if pre in self.index:
from_here = target[offset:]
for seek in self.index[pre]:
if from_here.startswith(seek):
yield seek
def is_match(self, target):
for match in self.find_matches(target):
return True
return False
def main():
srch = Searcher()
srch.add_seek_strings(["the", "words", "you", "want"])
with open("myfile.txt") as inf:
matched_lines = [line for line in inf if srch.is_match(line)]
if __name__=="__main__":
main()