算法/题解-KMP

题目链接:

luogu

题目描述:

给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置。然后输出next数组

题解:

这篇题解鸽了好久,因为我一直都没有完全理解看猫片,这东西是真的难。KMP的用处就是在母串里面找子串。
朴素做法是一位一位地匹配,判断子串和母串的字符是否相同,所以时间复杂度是O(mn)。(m、n是母串和字串的长度)
KMP就是通过一些神奇的操作跳过一些字符,以达到优化时间复杂度的效果。
具体的做法理解了其实并不复杂,一共就是3步。
1.找出子串内最长相同前后缀
举个例子:子串是AABAABAA
那么A和AA都是相同前后缀,但由于AA比较长,所以我们就选择它

很简单吧。。。
2.在后缀的最后设置一个指针,指向其最长相同前缀的最后
后缀的最后其实就是字符串的最后啦。。。
这个指针就是所谓的next数组

我们依次对子串的每一位进行这两步操作,第i位的指针就是next[i]

3.看代码。。。


int KMP(int len1,int len2){
    //母串的长度为len1,子串的长度为len2
//s1时母串,s2是子串
    k=0;  //字串指针
    for(int i=0;i<len1;i++){
       //和朴素算法一样,依次匹配母串的每一位
        while(k>0&&s1[i]!=s2[k]) k=next[k];   
        if(s1[i]==s2[k]) k++;   //如果匹配成功,匹配下一位
        if(k==len2) cout<<i-len2+2<<endl;  //如果全部匹配成功,输出答案
    }
 }

重点解释一下没加注释的那行代码,在朴素算法中如果匹配失败我们要把字串的指针归零(下面有朴素算法可以自行比较一下),但在KMP算法中我们直接把指针返回到next[i]记录的点,也就是我上面说的"相同前缀的最后“,因为既然这一段后缀和前缀是相同的,那么也就没有匹配再次匹配这一段的必要了,可以直接从相同部分的后一位开始匹配,这样就能达到节省时间的目的。
再举个例子:

A B C B C B C A A
i
</
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值