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)