KMP算法:字符串匹配的一种基本算法,比如:在BAB ABCAABCDA中匹配字符串ABCD(即在母串中查看是否包涵字串)
对字符串ABCD进行检索:
第一步:
发现A与B不匹配则,把A向后移动一位
第二步:
发现第一个字符A匹配,再寻找第二个字符B也匹配,再寻找第三个字符C不匹配,按照往常的做法将字符串ABCD整体后移一位,这样的方法最终可以找到字符串,但是过于耗时,下面进行KMP匹配,由于前面两项AB已经匹配,利用已经匹配的字符串计算后移的位数为2(怎么计算的最后讲解)
第三步:
发现A与母串不匹配则向后移动一位
第四步:
发现ABC都匹配,但是最后一个D与母串不匹配,则通过计算得到应向后移动3位
第五步:
发现第一个字符A可以匹配但是第二个B不匹配,则通过计算将字符串向后移动一位
第六步:
找到最后要匹配的字符串
如何通过计算得到子字符串下一步要向后移动的位数呢:通过计算已经匹配的字符串的长度减去已经匹配的字符串中前缀和后缀共有元素的字符串长度,比如:
ABC的前缀字符串为A,AB,后缀字符串为B,BC共有字符串长度没有,故长度为0 ,则后移的位数为3-0=3
ABCDAB的前缀字符串为A,AB,ABC,ABCD,ABCDA后缀字符串为B,AB,DAB,CDAB,BCDAB共有字符串为AB,则后移的位数为6-2=4
python实现:
str_next=[-999]*32
def get_next(t,str_next):
k=-1
j=0
str_next[j]=k
while(j<len(t)):
if((k==-1) or (t[j]==t[k])):
k=k+1;
j=j+1;
str_next[j]=k
else:
k=str_next[k]
def kmp(s,t,pos):
i=pos
j=0
while((i<len(s)) and (j<len(t))):
if((j==-1) or (s[i]==t[j])):
i=i+1
j=j+1
else:
j=str_next[j]
if(len(t)==j):
return i-len(t)
else:
return -1
if __name__ == "__main__":
s="abcabcabcacbab"
t="abcac"
pos=0
get_next(t,str_next)
index=kmp(s,t,pos)
print (index)