KMP字符串匹配算法
复习算法,整理一下这个KMP算法。
给定一个长为n的字符串S,和长为m的模式字符串P,判断P是否在S中出现,如果出现给出位移。
直接的想法就是,循环,从S的第i位开始,比较S[i,..,i+m-1]与P是否相同,这样的循环要n-m+1次,每次循环的时间复杂度O(m),那么总的时间复杂度就是O(nm)。
对字符串的查找有更快的线性时间算法,那就是KMP算法。K就是Knuth。
KMP算法的主要思想是,对模式字符串预处理,得到自身匹配的位移信息,然后在与目标字符串匹配的过程中,如果发生不匹配,那么接下来根据自身匹配的位移信息进行移位,例如S=abababca,P=ababca,模式字符串自身匹配位移信息如下,
1 2 3 4 5 6 P a b a b c a π 0 0 1 2 0 1
与目标字符串S的匹配过程,
1 2 3 4 5 6 S a b a b a b c a P a b a b c 在这一位出现不匹配, 根据自身匹配位移信息,将P移动如下, P a b a
那么就可以直接继续从第5位开始比较。
算法过程描述如下,
KMP-Matcher (T,P) n = length(T) m = length(P) π = Compute-Prefix (P) q = 0 for i = 1..n while q>0 and P[q+1]!=T[i] q = π[q] if P[q+1] = T[i] q = q + 1 if q = m print "pattern match at shift ", i-m q = π[q]
在上面的过程中,用到了计算自身匹配位移信息的函数,这个函数的过程如下,
Compute-Prefix (P) m = length(P) π[1] = 0 k = 0 for q = 2..m while k>0 and P[k+1]!=P[q] k = π[k] if P[k+1] = P[q] k = k + 1 π[q] = k return π
预处理过程的时间为O(m),匹配字符串的过程中每个字符只会处理一次,所以时间复杂度是O(n),整个的时间为O(n+m),线性时间复杂度。
用C/C++实现如下,
一个很好的参考,http://www.juliuschen.com/archives/21.html
比较详细的参考,http://blog.csdn.net/ultrasurf/article/details/1873589
C语言的实现,http://www.cppblog.com/suiaiguo/archive/2009/07/16/90237.html