Leetcode 28. 实现 strStr()|刷题打卡05

215 阅读4分钟

前言

离闯关挑战的倒计时还有一天的时间,而我还有5篇的文章没有发表出来...不过没关系,即使这个活动结束,我还会坚持刷题打卡,或者发文章的。今天要攻克的是KMP算法,KMP算法的作用其实很好理解,就是在当进行字符串匹配时,让子串尽可能地向前移动更多地距离,从而减少不必要的回溯。KMP算法的核心是next[]数组的代码理解和分析,也是我花了大量精力思考的难点,这里非常绕,还小小地套用了递归的想法,非常难懂也非常巧妙。 30CD930542999E100CAFF84549D296D4.jpg

题目描述:

实现 strStr() 函数。

给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回  -1

示例 1:

输入: haystack = "hello", needle = "ll"
输出: 2

示例 2:

输入: haystack = "aaaaa", needle = "bba"
输出: -1

说明:

当 needle 是空字符串时,我们应当返回什么值呢?这是一个在面试中很好的问题。

对于本题而言,当 needle 是空字符串时我们应当返回 0 。这与C语言的 strstr() 以及 Java的 indexOf() 定义相符。

来源:力扣(LeetCode)

链接:leetcode-cn.com/problems/im…

思路分析:

通读全题会发现,这道题是典型的利用KMP算法解决的问题,KMP算法的核心是避免不必要的回溯。所以,根据题目要求,自然可以通过KMP算法进行字符串的匹配并找到字符串相对应的位置。

  • 代码可以分为两个部分,一个是新建的getNext函数,还有一部分是主函数,主函数包含了对getNext函数的调用和字符串匹配过程的判断。
  • getNext中,要注意一点,当j01的时候,对应的next数组中的值都为0,但是为了后边的计算调用更加方便,所以直接设定它为-1i的值代表了后缀,j为前缀,所以她们两个的值相差为1,当字符串在ij的位置不匹配,且前缀与后缀不相等时,子串应该向前回溯,即
j=next[j];

回溯的意思为重新寻找位置从哪里开头并进行重新匹配,而next[j]的含义为当子串的第j个字符失配时,在子串中需重新和主串进行比较字符的位置,所以当第j个字符失配时,j需要回溯到next[j].这个用法类似于递归

而当前缀和后缀相同时,其所对应的next[i]的值与前缀即j的值有关,所以我们可以将前缀的长度赋值给next[i]

  • 在主函数中首先先调用getNext函数,获取子串needle的next数组,在for循环中,从i=0开始遍历,当j的值为子串长度减一时,说明已经出现了模式串,即匹配成功,直接返回对应值就可以了。

AC 代码:

KMP

class Solution {
public:
    void getNext(int *next,const string &s)
    {
        int j=-1;
        next[0]=j;
        for(int i=1;i<s.size();i++)
        {
            while(j>=0&&s[i]!=s[j+1])
            {
                j=next[j];
            }
            if(s[i]==s[j+1])
            {
                j++;
            }
            next[i]=j;
        }
    }
    int strStr(string haystack, string needle) {
        if(needle.size()==0)
        {
            return 0;
        }
        int next[needle.size()];
        getNext(next,needle);
        int j=-1;
        for(int i=0;i<haystack.size();i++)
        {
            while(j>=0&&haystack[i]!=needle[j+1])
            {
                j=next[j];
            }
            if(haystack[i]==needle[j+1])
            {
                j++;
            }
            if(j==(needle.size()-1))
            {
                return (i-needle.size()+1);
            }
        }
        return -1;
    }
};

总结:

KMP算法我学了好久。。。这道题也想了好久。。。还是要细心吧,一定要专心,不能遗漏任何细微的知识点。这道题也可以用提示中的indexOf()函数返回匹配成功的位置,这个方法也更加简单。翻看别人的答案,我发现这个依然有人用暴力法解这个题这里就不贴代码了,有兴趣的可以到对应链接的网站上自己做做,然后提交代码,检验是否正确。 谢谢阅读到这里的你,如果觉得我的文章对你有帮助的话,希望你能点个赞,不胜感激! 4S8F{~`RT)~FNLU9(6)$2MM.png

本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情