zoukankan      html  css  js  c++  java
  • 【KMP原理】【整理回顾】

    今儿套KMP模板做了个题,敏敏找我讲next[]数组的时候把我问懵了。具体原理都记不清了光靠模板凑得了一时凑不了一世啊,所以再捋一捋顺一顺,这次印象要深刻一点了;

    KMP与暴力匹配的优化区别就不再提了,O(m+n)的复杂度已经完胜了,直接进入正题...

    以下言论均是总结自该同学的,是不是原创我不清楚,链接反正是给你们吧...

    匹配串S,模式串T;

    首先是KMP的精华所在,next[]数组

    next[i]=k的意思为:T[i]前面有k个字符和字符串T的前k个字符相同,且T[i]不等于开始的k个字符之后的第k+1个字符,  1<=k<j

    所以从另一种解题层面上讲,next[len]的值表示字符串str[0...len-1]的后缀等于str[0...len-1]前缀的最长长度,例题运用:hdu 4763;

    举个例子:

        0 1 2 3 4 5 6 7 8

    S: a b c  a b c a b d

    T: a b  c a b d a b a

    1<=k<j, 因为T[0...1] = T[3...4],且T[2] != T[5],则next[5] = k = 2;

    若T[2] == T[5]时,next[5] = 0; --> 为什么呢?

    理解这个首先要明白利用next[i]我们可以做什么
    根据next[5] = 2,有T[3] == T[0],T[4] == T[1],又因为S[4] == T[4],S[3] == T[3],所以S[3] == T[0],S[4] == T[1](两对相当于间接比较过了)。
    接下来比较S[5]和T[2]是否相等,如果按问题的假设,T[2] == T[5],那么必然对于模式串T匹配到S[5]的位置仍是不匹配的;故此时的next[5]=0,模式串从T[0]与S[5]开始匹配;

    有一个问题来了:S[3]和T[0],S[4]和T[1]是根据next[5]=2间接比较相等,那S[1]和T[0],S[2]和T[0]之间又是怎么跳过比较的呢?
    我们一步步来,S[0]=T[0],S[1]=T[1],S[2]=T[2],

          而T[0] != T[1], T[1] != T[2](这里只是针对具体例子,但只要next[i] = k,那么S[1]、S[2]和T[0]间总会间接比较的

        ==> S[0] != S[1], S[1] != S[2],所以S[1] != T[0],S[2] != T[0]. 还是从理论上间接比较了。

    下面重点来了,next[]怎样取值以及进行字符串匹配时next值又有什么存在意义呢?

    next[]函数定义如下:
    (1)next[0] = -1 意义:任何串的第一个字符的模式值规定为-1。
    (2)next[j]  = -1 意义:情况①->模式串T中下标为j的字符与首字符相同,且j的前面的1~k个字符与开头的1~k个字符不相等(1≤k<j).

                    情况②->下标为j的字符前面的1~k个字符与开头的1~k个字符相等T[k]==T[j],(1≤k<j)。 如:T="abCabCad",T[0...2] == T[3...5]但T[3]=T[6],则next[6]=-1;
    (3)next[j]  = k  意义:模式串T中下标为j的字符,如果j前面的k个字符与开头的k个字符相等,且T[j] != T[k] (1≤k<j)。即T[0...k-1] == T[j-k ... j-1] 且T[j] != T[k];
    (4)next[j]  = 0  意义:除(1)(2)(3)的其他情况。

    对于不理解的可以看一下我给的链接里文章的例子,我就不再粘过来了。

    那么在进行字符串匹配时next值又该怎么使用呢?
    1. next[i]= -1 表示S[cur]和T[0]间接比较过了,不相等,下一次比较 S[cur+1] 和T[0]
    2. next[i]=0 表示比较过程中产生了不相等,下一次比较 S[m] 和T[0]。
    3. next[i]= k > 0 但k < n, 表示,S[cur]的前k个字符与T中的开始k个字符已经间接比较相等了,下一次比较S[cur]和T[k]相等;
    4. 其他值,不可能。

    基本KMP的知识就是这样了,今天先暂时到这里,日后会继续补充;

  • 相关阅读:
    架构师维度理解 程序=数据+算法
    vuejs 中 select 动态填充数据,后台的数据
    vuejs 的错误代码,有助于理解
    graphviz 绘制架构图
    graphviz 布局和子图,表格教程
    graphviz layer 教程(非布局)
    待学习
    Linux进程管理
    TCP连接的11种状态,三次握手四次挥手原因
    Linux基本命令使用(三)
  • 原文地址:https://www.cnblogs.com/LLGemini/p/4719299.html
Copyright © 2011-2022 走看看