Knuth-Morris-Pratt算法是一种在另一个字符串中查找一个字符串的好方法(因为我看到了 DNA,我猜你希望这个扩展到......数十亿?)。
# Knuth-Morris-Pratt string matching
# David Eppstein, UC Irvine, 1 Mar 2002
from __future__ import generators
def KnuthMorrisPratt(text, pattern):
'''Yields all starting positions of copies of the pattern in the text.
Calling conventions are similar to string.find, but its arguments can be
lists or iterators, not just strings, it returns all matches, not just
the first one, and it does not need the whole text in memory at once.
Whenever it yields, it will have read the text exactly up to and including
the match that caused the yield.'''
# allow indexing into pattern and protect against change during yield
pattern = list(pattern)
# build table of shift amounts
shifts = [1] * (len(pattern) + 1)
shift = 1
for pos in range(len(pattern)):
while shift <= pos and pattern[pos] != pattern[pos-shift]:
shift += shifts[pos-shift]
shifts[pos+1] = shift
# do the actual search
startPos = 0
matchLen = 0
for c in text:
while matchLen == len(pattern) or \
matchLen >= 0 and pattern[matchLen] != c:
startPos += shifts[matchLen]
matchLen -= shifts[matchLen]
matchLen += 1
if matchLen == len(pattern):
yield startPos
我获得 KMP python 代码的链接(和一个内置函数,由于运行时常量,它对于小问题会更快)。
对于前沿性能,使用字符串的前缀表和散列窗口作为基数 4 整数(在生物学中,您将它们称为 k-mers 或 oligos)。; )
祝你好运!
编辑:还有一个不错的技巧,您可以对包含第一个字符串中的每个前缀(总共 n 个)和第二个字符串中的每个前缀(总共 n 个)的列表进行排序。如果它们共享最大的公共子序列,那么它们在排序列表中一定是相邻的,因此从排序列表中最接近的另一个字符串中找到元素,然后取完全匹配的最长前缀。:)