【Leetcode】重复的子字符串

题目

重复的子字符串

题面

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

关键词

KMP,周期字符串问题

思路

方法一:

(官方题解)

暴力搜索所有子串,其要满足的条件是:

①s的长度是子串长度的倍数

②子串是s的前缀

③子串之后的所有字符满足s[i]==s[i-子串长度]

方法二:

(双倍字符串方法)

结论:把字符串翻一倍,掐头去尾,如果原字符串是该字符串的子串,那么原字符串是周期串。

证明见:https://writings.sh/post/algorithm-repeated-string-pattern

方法三:

(KMP求解)

公式:len(s)%(len(s)-maxLen)==0?true:false

其中maxLen为字符串s的最长公共前后缀长度

证明见:https://writings.sh/post/algorithm-repeated-string-pattern

代码

方法一

class Solution {
public:
    bool repeatedSubstringPattern(string s) {

        int n = s.size();
        for(int i=1;i*2<=n;i++){
           if(n%i==0){
               bool flag = true;
               for(int j=i;j<n;j++){
                   if(s[j]!=s[j-i]){
                        flag = false;
                        break;
                   }
                        
               }
               if(flag)
                 return true;
           }
       }
       return false;
    }
};

方法二:

class Solution {
public:
    void getnext(int next[],string s){
        next[0] = -1;
        int i,j;
        i=0;j=-1;
        while(i<int(s.size())-1){
            if(j==-1||s[i]==s[j])
                next[++i]=++j;
            else
                j = next[j];
        }
    }
    bool kmp(string s,string t){
        int n = t.size();
        int next[n];
        getnext(next,t);
        int i,j;
        i=0;j=0;
        while(i<int(s.size())&&j<int(t.size())){
            if(j==-1||s[i]==t[j]){
                i++;
                j++;
            }
            else
                j = next[j];
            
            if(j>=int(t.size())){
                return true;
            }
        }
        return false;
    }
    bool repeatedSubstringPattern(string s) {

       string t = s+s;
       t.erase(0,1);
       t.erase(t.size()-1,1);
       if(kmp(t,s))
         return true;
       else
        return false;
        
    }
};

方法三

class Solution {
public:
    void getnext(int next[],string s){
        next[0] = -1;
        int i,j;
        i=0;j=-1;
        while(i<int(s.size())-1){
            if(j==-1||s[i]==s[j])
                next[++i]=++j;
            else
                j = next[j];
        }
    }
    bool repeatedSubstringPattern(string s) {

        int n = s.size();
        int next[n];
        getnext(next,s);
        int maxlen = next[n-1]+1;
        if(maxlen==0||s[n-1]!=s[n-1-maxlen])
            return false;
        if(n%(n-maxlen)==0)
            return true;
        else
            return false;
    }
};

总结

继续学习

也没理解为什么方法二比方法一慢

人晕,“下次再说”

参考

重复的子字符串 - 重复的子字符串 - 力扣(LeetCode)

https://writings.sh/post/algorithm-repeated-string-pattern

https://mp.weixin.qq.com/s?__biz=MzI0NjAxMDU5NA==&mid=2475925123&idx=1&sn=f94678a2382c0add786fa36f2384f96c&chksm=ff22f90ec85570189587e6b6d18b98a31c50f2f3271b2288ccde8657e4bde5c9b92cf93fe921&token=2007736410&lang=zh_CN#rd

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值