字符串之KMP算法

本文介绍了KMP算法用于解决字符串匹配问题的基本原理,通过理解前缀和后缀概念,引入最长相同前后缀,构建next数组(前缀表),并详细阐述了如何在实际应用中处理冲突,优化匹配过程。
摘要由CSDN通过智能技术生成

一、应用题型

        首先我们要明白KMP算法要解决的是怎样的问题?一般用来解决字符串匹配的问题,比如有一个文本串s,一个模式串t,要检查s中是否包含有t,或者是s中是否可以由多个t组合在一起而成的等等诸如此类的题目,总的概括就是母串s是否包含一个或者是多个子串t。

二、KMP原理

        再将原理之前我们要明白前缀和后缀的概念:前缀就是以首字符开头但不包含尾字符的子串,后缀就是以尾字符结尾但不包括首字符的子串,举个例子:

s = abcab

前缀
    a
    ab
    abc
    abca
后缀
    b
    ab
    cab
    bcab

      下面就引入了最长相同前后缀的概念:有的书上也说明了最长相等前后缀的概念,其实这个是不准确的,因为我们要的是前后缀相同,相同就已经包括了相等,相等只是数量上的一致,并不一对应的字符相同,理解了这个我们接下来就举例说明为啥要引入最长相同前后缀这个概念:

s =  aabaabaaf

t =  aabaaf

       在上面两个字符串中,我们知道t与s进行匹配时,f与b发生冲突,说明了f之前的字符都是匹配的,但是子串到f时已经不匹配了,我们不可能让s中的字符从下表为1的地方开始,子串从头开始匹配,这样的话就浪费了太多的时间,而且大多是无效匹配的,我们希望的就是让母串不要移动,让子串来回移动,但是怎样让子串移动到合适的地方呢?这里就想到了最长公共前后缀的概念,在上面f是冲突的,但是前面是匹配的,我们就找冲突的前一个字符的前后缀长度就好了,这个长度恰好也是前缀后面的那个元素的下标,从这开始匹配,就不用在匹配之前匹配过的了;所以关键就是求解每个字符对应的最长公共前后缀的长度,也就是next数组;

      next数组求解方式如下:

void getindex(vector<int>&  next, string& s){

        int j = 0; //表示前缀的末尾位置,
        next[0] = 0;

       for(int i = 1;i < s.size();i++){  

           while(j>0  && s[i]!=s[j]){

                j = next[j-1];
          }

           if(s[i] == s[j]) j++;

         next[i] = j;

      }

}

   next数组就是前缀表,前缀表表示的就是i包括i之前最长的公共前后缀的长度(注意这句话:当前i以及i之前匹配过的最公共前后缀的长度即可),一旦知道了前缀表,我们就是知道了当字串不匹配的时候,该回退到哪里重新开始匹配;  

  三、应用

     求出来前缀表了,下面就是应用了如何应用呢,具体做法如下:

for(int i = 0;i < nums.size();i++){  i表示原字符串的位置,只用一边即可

      
       while(j > 0 && s[i]!=s[j]){  j指向的是匹配字符串的位置

               j = next[j-1];
        }

        if(s[i] == s[j]){

             j++;  
       }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值