KMP算法是用来做字符串匹配的。关于字符串匹配,最简单最容易想到的方法是暴利查找,使用双重for循环处理。
该方法的时间复杂度为O((n-m+1)*m) (n为目标串T长度,m为模式串P长度, 从T中寻找是否有P串存在)。
暴利的问题是在匹配中没有利用之前比较的信息。而这些信息可能是非常有用的。所以是可以进行优化以降低时间复杂度。
而KMP算法就是一个利用模式串来构造计算不匹配时计算模式串和目标串比较的位置,避免回溯。
KMP的思想为利用字符串的后缀串信息。
对于某个字符串y,如果有字符串w,满足字符串x = wy, 那么称y为x的后缀字符串。而其中最长的y为最长后缀字符串
我们对P字符串计算其后缀字符串信息,
KMP算法的伪代码如下:(注意下面的伪代码从1开始算起,而不是0)
KMP_MATCHER(T,P):
n = length(T)
m = length(P)
ComputeNextFunction(P)
k = 0
for q = 1 to n:
while (k > 0 && P[k +1] != T[i])
k = Next[k];
if [ P[k+1] == T[i] ]
++k
if [ k == m ]
print “Matched”
k = Next[k]
求Next数组的伪代码如下:
ComputeNextFunction(P):
m = length(P)
k = 0
Next[1] = 0
for q =2 to m
while k > 0 && P[k+1] != P[q]
k = Next[k]
if P[k+1] == P[q] :
++k
Next[q] = k
return Next
Next 数组求的就是最大的k值是的Pk是Pq的后缀字符串。
这样当到P串的第q个字符串和目标串不匹配的时候,从1到K的字符串和P[q-k -1] 到q个字符串是相等的(后缀字符串)。所以是不需要再进行比较的。可以直接跳过。