KMP算法中next数组到底有什么深意

要了解KMP首先我们回顾一下单纯暴力的BF算法

           现有字符串S(a,b,a,b,a,b,f),模式串P(a,b,a,b,f),根据BF算法首先我们将子串S[1,5]与P进行匹配,若匹配失败则再进行子串S[2,6]与P匹配,以此类推。可以看出字符串S的指针 i 在最坏的情况下(直到最后一个字符才发现不匹配)每次要回溯模式串P长度的步数。我们会想指针 i,j 是不是做了无用功。KMP算法解决了我们的疑惑。

        我们知道next数组中存放匹配失败时模式串指针需要回溯到的位置。那么仅仅是如此吗?那为何S的指针 i 并没有回溯,或许next数组还有更深层的意义。现在我们就探讨一下指针 i 为什么不回溯

 

        要想搞清楚指针 i 为什么不需要回溯,我们需要考虑一下如果回溯的话会如何。图中S,P分别代表主串和模式串,方块代表模式串中前缀后缀相同的部分,这部分信息next数组会告诉我们。图一为正常情况下回溯状态,根据BF算法 i 应回溯到S与P匹配第一个字符的下一个字符的索引(黑线O)。显然此时需要进行子串m,n的匹配,可以看出m,n分别为模式串P的前缀和后缀,并且m>k , 在这种情况下子串m必然与子串n不匹配(若m,n匹配, 那么k就不是模式串前缀后缀相等的最大长度),模式串自然也不会跟以O为起点S的子串匹配。至此我们最开始提出的问题似乎有些荒谬,因为BF算法与KMP算法有着本质上的不同,指针 i 的回溯是BF的事情,KMP并没有这种机制,也完全没有这种必要。

以上仅是笔者对KMP算法的一些个人的见解,也是初学KMP时难以理解的部分。

//next数组计算
 for(int i = 2,j = 0; i <= n; i ++ ){
        while(j && p[i] != p[j+1]) j = ne[j];
        if(p[i] == p[j + 1]) j++;
         ne[i] = j;
    }
    //模式串匹配
    for(int i = 1, j = 0;i <= m; i ++){
        while(j && s[i] != p[j+1]) j = ne[j];//
        if(s[i] == p[j+1]) j ++;
        if(j == n) {
            cout<<i - n <<" ";
            j = ne[j];
        }
    }

  

        

             

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值