KMP是三位大牛:D.E.Knuth、J.H.Morris和V.R.Pratt同时发现的。其中第一位就是《计算机程序设计艺术》的作者!!
算法主要的作用就是匹配字符串,我们设置T为主串,P为子串。配置在T中是否包含P的话,我们当然可以通过暴力匹配的方式来实现。python代码实现非常简单如下。
def naive_match(s, p):
m = len(s); n = len(p)
for i in range(m-n+1):#起始指针i
if s[i:i+n] == p:
return True
return False
算法最最重要的就是找到前后缀最长公共元素,以‘ABCDABD’为例:
1.由"next[j] == k;"这个条件,我们可以得到A1子串 == A2子串(根据next数组的定义,前后缀那个)。
2.由 “next[k] == 绿色色块所在的索引;” 这个条件,我们可以得到B1子串 == B2子串。
3.由 “next[绿色色块所在的索引] == 黄色色块所在的索引;” 这个条件,我们可以得到C1子串 == C2子串。
4.由1和2 (A1 == A2,B1 == B2) 可以得到 B1 == B2 == B3。
5.由2和3 (B1 == B2, C1 == C2) 可以得到 C1 == C2 == C3。
6.B2 == B3可以得到C3 == C4 == C1 == C2
def get_next(P):
next_list = [0 for i in range(len(P))]
j,k,next_list[0] = 0,-1,-1
while j<len(P)-1:
if k ==-1 or next_list[j] == next_list[k]:
j += 1
k += 1
next_list[j]=k
else:
k = next_list[k]
return next_list
def my_kmp(T,P):
T_len = len(T)
P_len = len(P)
next_P = get_next(P)
#主串位置为i,模式串为j
i,j = 0,0
while i< T_len and j < P_len:
if j == -1 or T[i]==P[j]:
i +=1
j+=1
else:
j = next_P[j]
if j == P_len:
return i-j
else:
return -1
if __name__ == '__main__':
T = 'adsaafaaffdsaf'
P = 'afaaf'
print(get_next(P))
print(my_kmp(T,P))