zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    LeetCode Subsets II
    LeetCode Rotate Image
    LeetCode Palidrome Number
    LeetCode Generate Parentheses
    LeetCode Maximum Subarray
    LeetCode Set Matrix Zeroes
    LeetCode Remove Nth Node From End of List
    Linux Loop设备 使用
    Linux 文件系统大小调整
    LeetCode N-Queens II
  • 原文地址:https://www.cnblogs.com/Frandy/p/string_match_kmp.html
Copyright © 2011-2022 走看看