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

  • 相关阅读:
    待办
    安卓微信浏览器修改的代码总是不生效
    微信浏览器内核2
    微信浏览器内核
    随记
    三次握手最后一个ack没有收到怎么办?
    判断偶数:
    利用kubeadm工具安装Kubernetes1.15版本
    kubernetes安装Helm
    最大子列和(附加子列初始元素和末尾元素)
  • 原文地址:https://www.cnblogs.com/Frandy/p/string_match_kmp.html
Copyright © 2011-2022 走看看