力扣每日一刷Day 17

Practice Day seventeen:Leetcode T 435

由于Day 16我们已经对KMP算法进行了超详细的讲解,虽然有些王婆卖瓜的嫌疑,但我仍认为我没有夸大其词。总而言之,今天我不会讲KMP的原理了,而是讲解实现方法。

我这里还有一份利用周期性实现KMP算法的讲解链接,有兴趣的兄弟姐妹可以看看,也是挺有意思的,我不再对此进行讲解
https://zhuanlan.zhihu.com/p/661673949https://zhuanlan.zhihu.com/p/661673949

今天我们学习另一种KMP实现方法

该方法出自B站up主 NotOnlySuccess

视频链接如下

https://www.bilibili.com/video/BV1Er421K7kF/?spm_id_from=333.788.videopod.sections&vd_source=f8b81fa5a70ab21de75192e5c7ec720chttps://www.bilibili.com/video/BV1Er421K7kF/?spm_id_from=333.788.videopod.sections&vd_source=f8b81fa5a70ab21de75192e5c7ec720c

这位老哥提出了另一种KMP构建法:把模式串链接到主串上,当组合串的某一个元素的next数组记录的步长与模式串长度相同,即为找到了所需字符。

真是一种十分天才的方法,完美的利用了前缀函数的性质。模式串与主串的相接,实现了主串数组局部确立,从而可以使用前缀函数求解。

这里模式串链接到主串上面的时候,需要在模式串后面加一个与模式串无关的字符,以保证没有局部匹配的情况发生。如果你不清楚什么是局部匹配,请移步Day 16进行阅读相关部分。(局部匹配这个词是我造的,我没有在任何一个视频或者讲解中看到对于这种情况的说明,如有雷同,纯属巧合)。

让我们来看看老哥的代码是如何实现的。

1 一些基础的准备工作就不讲解了,该讲的Day 16已经讲解过了

    int strStr(string main, string pattern) {
        int n = main.size(), m = pattern.size();
        string s = pattern + '#' + main;
        vector<int> pi(s.size());

2 然后是构造整个组合串的pi数组,返回符合条件对象,找不到就返回-1。

其实这和我们Day 16实现的KMP挺像的,只不过匹配流程直接一步到位了。

这里return  i-m*2是因为我们向主串中加入了模式串和一个不相干的字符,所以不用+1,而且由于模式串挤占了位置,所以要减去m*2。

        for (int i = 1; i < s.size(); i++) {
            int len = pi[i-1];
            while (len && s[i] != s[len]) {
                len = pi[len - 1];
            }
            if (s[i] == s[len]) {
                pi[i] = len + 1;
                if (pi[i] == m) {
                    return i - m * 2;
                }
            }
        }
        return -1;
    }

今天的大部分篇幅都在Day 16中讲解,所以今天的实现十分简短。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值