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

原文地址:https://www.cnblogs.com/Frandy/p/string_match_kmp.html