顿悟KMP算法

顿悟KMP算法

今天看代码随想录视频时突然顿悟了KMP算法,记录一下。

视频链接如下:https://www.bilibili.com/video/BV1PD4y1o7nd/?spm_id_from=pageDriver&vd_source=dbf9af553125b4306a86f9ae92b33b98

建议看完我这里写的再看视频就看的懂了。

那么所谓的KMP算法就是为了省事,不需要重新从开始进行匹配

上例子:
比如aabaaf,假设到 f 这一位不相同了怎么办,怎么才能省事?
发现了吗?f 前面有几位是和字符串 aabaaf 的开头相同的?
是 aa 对吧
也就是说到 f 这一位不相同了,f前面的 aa 和字符串开头的aa,都是相同的,都是aa,那么我就可以图省事,直接从aabaaf的开头,也就是第一个aa后面的第一个字符b进行继续比较,来比较原来 f 没对上的那个字符。
这时候就达到了省事的效果。

再上例子:aabcaabf
那么假设到 f 这一位不相同了,我直接去哪里比?
直接从 c 开始吧,是不是?
为什么呢?
因为f前面的 aab 和字符串 aabcaabf 的开头 aab 是相同的。
为了省事,我直接从aab后面的 c 开始匹配
因为被比较的字符串A(A为随便起的字符串名)在与aabcaabf 在 f 不一样,那么f前面的aab,A的对应位置也是aab,只不过在f对应的位置上,A不是f,而是其他的随便什么字符。

那么就到了视频当中讲的前缀和后缀的问题了。
还是以aabcaabf为例,当你把 f 去掉以后,变成了aabcaab, 此时前缀是谁,是从开头的第一个字符a开始的任意长度连续字符串都是前缀吧,如a,aa,aab,aabc…
后缀是谁?是带着字符串最后一个字符b的任意长度连续字符串都是后缀,但是方向不是从后至前的方向,仍然是从前至后的方向,比如b,ab,aab,caab,bcaab,…
你品,你仔细品

那么就好理解了,最长相等前后缀是谁?就是aab吧
也就是aabcaabf 中 f 前面 和 aabcaabf从头开始的最长相同字符串aab

明白了吧

主要是思想,其他花里胡哨的,思想明白,也没有啥不理解的了吧

现在你可以去看视频了

————————————————————
Next数组求法:
求next数组和最后的匹配是一样的
先不相等就一直跳
如果相等就加加
一个是next数组赋值
一个是如果等于长度就输出

class Solution {
public:
    int strStr(string haystack, string needle) {
        vector<int>next(needle.size());
        int k=0;
        for(int i=1;i<next.size();i++){
           while(k>0 && needle[i]!=needle[k]){
               k=next[k-1];
           }
           if(needle[i]==needle[k]){
               k++;
           }
           next[i]=k;
        }
        int j=0;
        for(int i=0;i<haystack.size();i++){
            //如果不相等就一直跳
            while(j>0 && haystack[i]!=needle[j]){
                j=next[j-1];
            }
            if(haystack[i]==needle[j]){
                j++;
            }
            if(j==needle.size()){
                return i-(needle.size()-1);
            }  
        }
        return -1;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值