代码随想录算法训练营第九天| LC28. 找出字符串中第一个匹配项的下标、LC459. 重复的子字符串、字符串章节总结、双指针回顾

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

题目链接:28. 找出字符串中第一个匹配项的下标

做题情况:虽然是二刷代码随想录,但是KMP算法自己总体思路还是那么混乱以及代码实现也无从下手,继续看卡哥视频和代码随想录书相关部分后,对此算法有了更深的理解,主要在以下几点:① 理解前缀表,也就是next数组怎么回事 ② next数组求解的具体实现 ③咋样使用next数组做匹配以及具体实现,其中next数组求解主要是以下三点:① 初始化next数组 ② 处理前后缀不相同的情况 ③处理前后缀相同的情况,然后自己对卡哥所给的代码重新抄写了一遍,后面还有好好复习,以及自己自己独立去实现,下面是卡哥的代码:

//前缀表统一减一的代码实现
class Solution {
public:
    void getNext(int* next, const string& s){
        int j=-1;
        next[0]=j;
        for(int i=1;i<s.size();i++){//注意i从1开始
            while(j>=0&&s[i]!=s[j+1]){//前后缀不相同
                j=next[j];
            }
            if(s[i]==s[j+1]){//找到相同的前后缀
                j++;
            }
            next[i]=j;//将j(前缀的长度)赋值给next[i]
        }
    }
    int strStr(string haystack, string needle) {
        if(needle.size()==0){
            return 0;
        }
        int next[needle.size()];
        getNext(next, needle);
        int j=-1;//next数组中记录的起始位置为-1
        for(int i=0;i<haystack.size();i++){//注意i就从0开始
            while(j>=0&&haystack[i]!=needle[j+1]){//不匹配
                 j=next[j];//j寻找之前的匹配位置
            }
            if(haystack[i]==needle[j+1]){//匹配,j和i同时向后移动
                j++;//i的增加逻辑再for循环中
            }
            if(j==(needle.size()-1)){//文本串s中出现了模式串t
                return (i-needle.size()+1);
            }
        }
        return -1;
    }
};
//前缀表不减1来构建next数组
class Solution {
public:
    void getNext(int* next, const string& s){
        int j=0;
        next[0]=j;
        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;
        }
    }
    int strStr(string haystack, string needle) {
        if(needle.size()==0){
            return 0;
        }
        int next[needle.size()];
        getNext(next, needle);
        int j=0;//next数组中记录的起始位置为-1
        for(int i=0;i<haystack.size();i++){//注意i就从0开始
            while(j>0&&haystack[i]!=needle[j]){//不匹配
                 j=next[j-1];//j寻找之前的匹配位置
            }
            if(haystack[i]==needle[j]){//匹配,j和i同时向后移动
                j++;//i的增加逻辑再for循环中
            }
            if(j==(needle.size())){//文本串s中出现了模式串t
                return (i-needle.size()+1);
            }
        }
        return -1;
    }
};

构造next数组从初始化、相同情况和不相同情况(特别其中while循环)的逻辑理解就行

LeetCode 459 重复的子字符串

题目链接:459. 重复的子字符串

做题情况:毫无头绪的一道题目,看完卡哥视频和代码随想录书相关部分后,才知道本题有多种解法:① 暴力解法(这种解法理解思路即可) ② 移动匹配(自己理解起来比较别扭,我觉得凭我现有的知识记住和温习即可) ③ KMP方法(感觉很巧妙的一种的方法,原来next数组还可以这样用),自己又把卡哥给的代码给抄了一遍,具体如下:

//移动匹配方法
class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        string t=s+s;
        t.erase(t.begin());
        t.erase(t.end()-1);
        if(t.find(s)!=std::string::npos)return true;
        return false;
    }
};
//前缀表减1来构建next数组
class Solution {
public:
    void getNext(int* next, const string& s){
        int j=-1;
        next[0]=-1;
        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;
        }
    }

    bool repeatedSubstringPattern(string s) {
        if(s.size()==0){
            return false;
        }
        int next[s.size()];
        getNext(next, s);
        int len=s.size();
        if(next[len-1]!=-1&&len%(len-(next[len-1]+1))==0){
            return true;
        }
        return false;
    }
};
//前缀表不减1来构建next数组
class Solution {
public:
    void getNext(int* next, const string& s){
        int j=0;
        next[0]=j;
        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 len=s.size();
        if(next[len-1]!=0&&len%(len-(next[len-1]))==0){
            return true;
        }
        return false;
    }
};

虽然是二刷,但是今天大部分都是在学习卡哥的讲解和抄代码,独立完成还是那么难,呜呜

字符串章节总结

具体总结见卡哥总结
我觉得这章节这些题目得过一段时间又得多刷几遍,多思考总结,尽量自己独立快速完成,有太多技巧且代码实现能力要求也高

双指针回顾

具体总结见卡哥总结
这些双指针题目和字符串题目一样的建议

今天花了五个小时左右来完成任务,还是有点懵,后面多抽些时间来看看和回顾

贵在坚持,加油,共勉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值