代码随想录刷题随记8-KMP

本文介绍了KMP算法在解决字符串查找问题中的应用,包括找到第一个匹配项的下标、检测重复子串模式以及利用KMP原理优化重复子串检测。同时提供了三种不同的解题方法和相应的代码实现。
摘要由CSDN通过智能技术生成

代码随想录刷题随记8-KMP

KMP原理:文章链接

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

标准的kmp类型的题
leetcode链接

class Solution {
public:
    
    vector<int> getnext(string s){
        if(s.size()==1){
            return {-1};
        }
        if(s.size()==2){
            return {-1,0};
        }
        vector<int>next=vector<int>(s.size(),0);
        next[0]=-1;
        next[1]=0;
        int cnt=0;
        int x=2;
        while(x<s.size()){
           if(s[x-1]==s[cnt]){
            next[x++]=++cnt;
           } 
           else if(cnt>0){
            cnt=next[cnt];
           }
          else{
           next[x++]=0;
          }
        }
        return next;
    }
    int strStr(string haystack, string needle) {
        if(needle.size()>haystack.size())
          return -1;
        vector<int> next=getnext(needle);
        int x=0;
         int y=0;
         while(x<haystack.size()&&y<needle.size()){
            if(haystack[x]==needle[y]){
                x++;
                y++;
            }
            else if(y>0){
                y=next[y];
            }
            else{
                x++;
            }
         }
         return  y==needle.size()? x-y:-1;
    }

};

459.重复的子字符串

leetcode 链接
方法1,暴力枚举
我们只需要判断,以第一个字母为开始的子串就可以,所以一个for循环获取子串的终止位置就行了。 而且遍历的时候 都不用遍历结束,只需要遍历到中间位置,因为子串结束位置大于中间位置的话,一定不能重复组成字符串。复杂度 O ( N 2 ) O(N^2) O(N2)
解题代码:

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
    for(int i=1;2*i<=s.size();i++){
        if(s.size()%i==0){
            bool match=true;
        for(int j=i;j<s.size();j++){
            if(s[j]!=s[j-i]){
              match=false;
              break;
            }
        }
        if(match)
          return match;
        }
       
    }
     return false;
    }
};

方法2
我们将两个 sss 连在一起,并移除第一个和最后一个字符。如果 sss 是该字符串的子串,那么 sss 就满足题目要求。
其中判断是否为字串采用kmp算法
解题代码:

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        return (s + s).find(s, 1) != s.size();
    }
};

方法三kmp
活用kmp的前后缀匹配思想

在由重复子串组成的字符串中,最长相等前后缀不包含的子串就是最小重复子串,这里拿字符串s:abababab 来举例,ab就是最小重复单位
在这里插入图片描述
数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。

解题代码:

class Solution {
public:
    vector<int> getnext(string s){
        if(s.size()==1){
            return {-1};
        }
        if(s.size()==2){
           return {-1 ,0};
        }
        vector<int> next=vector<int>(s.size()+1,0);
        next[0]=-1;
        next[1]=0;
        int x=2;
        int cnt=0;
        
        while(x<s.size()+1&&cnt<s.size()){
            if(s[x-1]==s[cnt]){
                next[x++]=++cnt;
            }
            else if(cnt>0){
                cnt=next[cnt];
            }
            else{
                next[x++]=0;
            }
        }
        return next;
    }
    bool repeatedSubstringPattern(string s) {
        if(s.size()<=1)
           return false;
           if(s.size()==2){
             return s[0]==s[1];
           }
        vector<int> next=getnext(s);
        int sublen=next[s.size()];
        int len=s.size();
        return (sublen!=0)&&(len%(len-sublen)==0)? true:false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值