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

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

KMP原理:文章链接

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

标准的kmp类型的题
leetcode链接

cpp 复制代码
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)

解题代码:

cpp 复制代码
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算法

解题代码:

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

方法三kmp

活用kmp的前后缀匹配思想

在由重复子串组成的字符串中,最长相等前后缀不包含的子串就是最小重复子串,这里拿字符串s:abababab 来举例,ab就是最小重复单位

数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环。

解题代码:

cpp 复制代码
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;
    }
};
相关推荐
yuanbenshidiaos14 分钟前
c++---------数据类型
java·jvm·c++
十年一梦实验室43 分钟前
【C++】sophus : sim_details.hpp 实现了矩阵函数 W、其导数,以及其逆 (十七)
开发语言·c++·线性代数·矩阵
taoyong0011 小时前
代码随想录算法训练营第十一天-239.滑动窗口最大值
c++·算法
这是我581 小时前
C++打小怪游戏
c++·其他·游戏·visual studio·小怪·大型·怪物
Uu_05kkq1 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
fpcc1 小时前
跟我学c++中级篇——C++中的缓存利用
c++·缓存
呆萌很1 小时前
C++ 集合 list 使用
c++
诚丞成2 小时前
计算世界之安生:C++继承的文水和智慧(上)
开发语言·c++
1nullptr3 小时前
三次翻转实现数组元素的旋转
数据结构
TT哇3 小时前
【数据结构练习题】链表与LinkedList
java·数据结构·链表