zoukankan      html  css  js  c++  java
  • KMP(Knuth-Morris-Pratt)字符串模式匹配

    KMP是一种在一个字符串中定义另一个串的高效算法。简单匹配算法的时间复杂度为O(m*n);KMP匹配算法的时间复杂度为O(m+n)。

    一个极端的例子是:在S="AAAAAA...AAB"(100个A)中查找T="AAAAAAAAAB",简单匹配算法每次都是匹配到T的结尾,发现字符不同,然后T的下标回溯到开始,S的下标也要回溯相同长度后增1,继续比较。如果使用KMP算法,就不需要回溯。

    KMP构造模式串T的模式函数next,构造方法:

    1. next[0] = -1 任何串的第一个字符的模式值规定为-1
    2. next[j] = -1  如果T[j]与T[0]相同,且j的前面k个字符与开头的k个字符不等(或者相等但T[k]==T[j])(1<=k<j)
    3. next[j] = k 如果T[j]的前面k个字符与开头的k个字符相等,且T[k]!=T[j])(1<=k<j)
    4. next[j] = 0 除上面3种情况的其他情况(j!=0且前面不存在k个字符与开头的k个字符相等,或者是相等但T[j]==T[k] (1<= k<j)

    在字符串S中查找模式串T,若S[m]!=T[n],那么T[n]的模式串函数next[n]告诉我们下一步应该比较哪两个字符:

    1. next[n] = -1 表示S[m]和T[0]间接比较过了,不相等,下一次比较S[m+1]和T[0]
    2. next[n] = 0 表示比较过程中产生了不相等,下一次比较S[m]和T[0]
    3. next[n] = k (0<k<n),表示S[m]的前k个字符与T中的开始k个字符已经间接比较相等了,下一次比较S[m]和T[k]

    结论:KMP方法在查询的时候,S不用回溯。

    计算模式串

    例1:T="abCabCad"

    答案:next = [-1 0 0 -1 0 0 -1 4]

    解答:

    next[3] = -1的原因:(1)首先,T[3]==T[0]; (2)其次,k=1时T[2]!=T[0],k=2时T[1]+T[2]!=T[0]+T[1],即j前面的k个字符与开头k个字符不等。

    next[6] = -1的原因:(1)T[6]==T[0]; (2)虽然j前面的3个字符与开头3个字符相等,但T[3]==T[6]

    例2: T="AAAAAAAAAB"

    答案:next=[-1 -1 -1 -1 -1 -1 -1 -1 -1 8]

    解答:next[9] = 8告诉我们,当S[m]!=T[9]时,下次查询S[m]和T[8]

  • 相关阅读:
    Linux 软件安装
    大型网站架构设计原理(书的目录)
    Spring Cloud 学习笔记(二)——Netflix
    Spring Cloud 学习笔记(一)——入门、特征、配置
    RocketMQ与Kafka对比
    分布式开放消息系统(RocketMQ)的原理与实践(转)
    JavaScript Event Loop
    双向链表
    MutationObserver()观察者构造函数用法
    jsonp跨域
  • 原文地址:https://www.cnblogs.com/qionglouyuyu/p/13418955.html
Copyright © 2011-2022 走看看