首页 > 编程语言 >代码随想录算法训练营第八天LeetCode28, 459

代码随想录算法训练营第八天LeetCode28, 459

时间:2023-01-09 23:25:46浏览次数:71  
标签:子串 459 return int 随想录 next 后缀 LeetCode28 size

代码随想录算法训练营第八天|LeetCode28,459

Leetcode 28 找出字符串中第一个匹配项的下标

题目链接:https://leetcode.cn/problems/find-the-index-of-the-first-occurrence-in-a-string/description/
//kmp算法
class Solution {
public:
    //kmp算法
    //写一个构建next的数组
    void getNext(int *next, const string &s){
        //构建next数组要知道:next数组的每个值是每个模式子串的最长相等前后缀值
        //j代表每个子串的前缀末尾以及最长相等前后缀值
        int j = 0;
        //初始化
        next[0] = 0;
        //i代表每个子串的后缀末尾
        //因为一般两个元素才算前后缀,所以让 i = 1;
        //遍历每个子串,记录每个子串的最长相等前后缀
        //比如aabaaf,就是求aa的最长相等前后缀,aab的最长相等前后缀,aaba的最长相等前后缀。。依次类推
        for(int i = 1; i < s.size(); i++){
            //前后缀不匹配时,当s[i]不等于s[j],j要通过next[j-1]的值跳回 
            while(s[i] != s[j] && j > 0){
                j = next[j-1];
            }
            //前后缀匹配时,当s[i]等于s[j]
            if(s[i] == s[j]){
                j++;
                //next[i] = j; error 不能写在if里,加入某子串无匹配,next[i]该填入何值?
            }
            next[i] = j;
        }

    }

    //模式串和给定串进行匹配
    int strStr(string haystack, string needle){
        if(needle.size() == 0){
            return 0;
        }
        int next[needle.size()];
        getNext(next, needle);
        //假设模式串aabaaf,给定串aabaabaaf
        int j = 0;
        for(int i = 0; i < haystack.size(); i++){
            while(haystack[i] != needle[j] && j > 0){
                j = next[j-1];
            }
            if(haystack[i] == needle[j]){
                j++;
            }
            //为什么判断条件不是j == needle.size()-1。因为如果模式串和给定串的最后一个字符匹配上,j还要++
            if(j == needle.size()){
                return(i - needle.size() + 1);
            }
        }
        return -1;

    }
};
视频讲解链接:https://www.bilibili.com/video/BV1PD4y1o7nd/?spm_id_from=pageDriver&vd_source=8d6cce160628d93add1e5fa9299f622d
文章讲解链接:https://programmercarl.com/0028.实现strStr.html#其他语言版本

LeetCode 459 重复的子字符串

题目链接:https://leetcode.cn/problems/repeated-substring-pattern/description/
//需要转换思路了,搁这三过家门而不入呢。使用next的思路倒没错,但是repeatedSubstringPattern函数体里写得有问题,需要重新想想,还是kmp掌握得不熟练
class Solution {
public:
    //检查一个字符串是否一个子串多次构成
    //联想kmp算法,对这个字符串求next数组

    void getNext (int *next, const string &s){
        //初始化
        next[0] = 0;
        //j指向子串的前缀的末尾以及最长相等前后缀值
        int j = 0;
        //i指向子串的后缀末尾,所以i从1开始
        //遍历每个子串
        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;
        }
        
    }

    bool repeatedSubstringPattern(string s) {
        int next[s.size()];
        getNext(next, s);
        if(s.size() == 2 && s[0] == s[1]) return true;
        int i;
        for(i = 0; i < s.size(); i++){
            if(next[i] == 1) break;
        }
        if(i == s.size() || i == s.size()-1) return false;
        int counts = i;
	    if((s.size()-counts)/counts < 0 || (s.size()-counts)%counts != 0) return false;
        for(; i < s.size() -1 ; i++){
            if(next[i] + 1 != next[i+1]) return false;

        }
        return true;
        
            
    }

};
视频讲解链接:https://www.bilibili.com/video/BV1cg41127fw/?spm_id_from=333.788&vd_source=8d6cce160628d93add1e5fa9299f622d
文章讲解链接:https://programmercarl.com/0459.重复的子字符串.html#kmp
class Solution {
public:
    //检查一个字符串是否一个子串多次构成
    //联想kmp算法,对这个字符串求next数组
    void getNext (int *next, const string &s){
        //初始化
        next[0] = 0;
        //j指向子串的前缀的末尾以及最长相等前后缀值
        int j = 0;
        //i指向子串的后缀末尾,所以i从1开始
        //遍历每个子串
        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;
        }
        
    }
    bool repeatedSubstringPattern(string s) {
        if(s.size() == 0) return false;
        int next[s.size()];
        getNext(next, s);
        //
        int i = s.size();
        if(next[i - 1] != 0 && i % (i - next[i - 1]) == 0){
            return true;
        }
        return false;

    }
};

标签:子串,459,return,int,随想录,next,后缀,LeetCode28,size
From: https://www.cnblogs.com/shadowbringer/p/17038823.html

相关文章