首页 > 其他分享 >重复的子字符串问题

重复的子字符串问题

时间:2023-07-20 09:47:40浏览次数:31  
标签:string 重复 next 问题 int 循环 KMP 字符串

1.重复子字符串问题分析

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

  有点难度,值得反复刷;本质找 循环子串问题,可以 暴力求解或者移位

2.解法

2.0  暴力求解

  设 字符串 S 由 s'重复构成,则 S=s's's's's's'  (n个s' , s' 长度为 i );

  则 :S长度就是 n*i ,那么 我们循环遍历时,固定s'长度 i ,当n%i==0时,判断 s[j] 与 s[j-i] 是否相等;

  其实也就是从第二个 s' 开始,我往前平移一个s'长度(也就是 i ) , 理论上是不变的【因为循环】

  所以如果我能找到这样的循环,就说明有重复子串

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int n = s.size();
        for (int i = 1; i * 2 <= n; ++i) 
        {
            //相当于i用来固定前缀的长度的
            if (n % i == 0) {
                bool match = true;
                for (int j = i; j < n; ++j) {
                    if (s[j] != s[j - i]) {
                        match = false;
                        break;
                    }
                }
                if (match) {
                    return true;
                }
            }
        }
        return false;
    }
};

 

2.1 移位法

 原理:

  假设判断字符串s(n个字符构成)是不是由重复子串构成的,我们先将两个字串拼成一个大的字符串:S = s + s(S 有2n个字符);

  字符串拼接的最底层思想是:使用字符串移位来判断字符串是否由重复子串(循环节)构成,因为S这个大的字符串 其实包含了字符串s的所有移位字符串。令字符串字符索引从0开始,[m,n]表示S中索引为m到索引为n的这一段字符,索引为闭区间,则[0,n-1]即S的前一半字符表示原始字符串s;[1,n]表示s右移1位的状态;[2,n+1]表示s右移2位的状态;······;[n,2n-1]即S的后半拉字符串可以理解为s移n位的状态,此时s已经移回了原始的状态了;

  此外我们不难知道如果一个没有循环节的字符串在移位时必须要右移n次他才能移回它的原始状态,而有循环节的字符串最多只需要n/2次(只有两个循环节,三个和四个同理);所以当S砍去首尾字符时,对于没有循环节的字符串s,相当于砍去了[0,n-1]的原始状态和[n,2n-1]这个移位n次的又回归原始的状态,我们在[1,2n-2]范围内只能找到s移位1,2,···,n-1位时的状态,所以在[1,2n-2]内是不存在无循环节的s的;但是对于有循环节的s来说,n/2 <= n-1,所以一定存在至少一个移位状态为s,即最少存在一个s(其实对于有循环节的s来说,不考虑移位状态我们也能明白[1,2n-2]内一定至少有一个s,例如对于有两个循环节的s:组成S的前一个s的后一半字符 + 组成S的后一个s的前一半的字符 == s;三个循环节的s更不用说了)

  代码如下:【KMP的实现见下文】 >  >  > 这里也可以用库函数

    bool repeatedSubstringPattern(string s) {
        string n = s + s;
        n.erase(n.begin());
        n.erase(n.end() - 1);
        if (KMP(n, s))
            return true;
        else
            return false;
    }

 

2.2 优化KMP算法

  代码随想录中对于这一部分解释蛮好的,不再重复叙述,参考链接:代码随想录 (programmercarl.com)

  自实现代码如下,这里只是用到了 KMP前缀表的概念,实际并未完全参照KMP

  

class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        int N = s.size();
        int* next = new int[N];
        int j = -1; 
        next[0] = -1;
        for (int i = 1; i < N; ++i)
        {
            while (j >= 0 && s[i] != s[j + 1])
                j = next[j];
            if (s[i] == s[j + 1])
                ++j;
            next[i] = j;
        }
        // next[N - 1] != -1是避免只有一个单独串情况 % 也等于0
        if (next[N - 1]!=-1 &&  N% (N - (next[N-1]+1)) == 0)
            return true;
        else
            return false;
    }
};

 

 

2.3 补充KMP算法实现

 bool KMP(string& origin, string& pattern)
    {
        int N = pattern.size();
        int* next = new int[N];
        getNext(pattern, next);
        int j = -1;
        for (int i = 0; i < origin.size(); ++i)
        {
            while (j >= 0 && origin[i] != pattern[j + 1])
                j = next[j];
            if (origin[i] == pattern[j + 1])
                ++j;
            if (j == (N - 1))
                return true;
        }
        return false;
    }
    void getNext(string& s, int* next)  //得到前缀表
    {
        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;
        }
    }

 

标签:string,重复,next,问题,int,循环,KMP,字符串
From: https://www.cnblogs.com/Kellen-Gram/p/17567327.html

相关文章

  • pythcharm问题集锦
    1.无法加载文件*\venv\Scripts\activate.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅https:/go.microsoft.com/fwlink/?LinkID=135170中的about_Execution_Policies解决方法:https://www.cnblogs.com/91key/articles/16770455.html......
  • 解决Xavier桌面共享闪退的问题
    一、修复DesktopSharing闪退问题表现:点击共享桌面应用,无法打开问题原因:系统bug解决方法:1、打开配置文件sudovim/usr/share/glib-2.0/schemas/org.gnome.Vino.gschema.xml2、在文件最后两个标签之前加一段key代码 3、编译生效sudoglib-compile-schemas/usr/share/gl......
  • 一维资源分配问题(java实现)
    一维资源分配1.问题介绍设有总量为a的某种原料,用于生产n种产品。假设用于生产第k种产品生产的数量为\(x_k\),并获得收益\(\varphi(x_k)\),问应该如何分配n种产品的资源使用量使得总收益最大。2.Solution\(k\):生产第k种产品的决策阶段;\(x_k\):投入到第k种产品生产的资......
  • 剑指 Offer 67. 把字符串转换成整数
    题目classSolution{public:intstrToInt(stringstr){if(str.size()==0)return0;#空字符串情况intcur=0;while(str[cur]=='')cur++;#直接从非空字符开始处理booloverflow=false;......
  • 向我提问题吧!
    阅读本文大概需要3分钟。一直以来,我在各个渠道都会收到各种各样的问题,有问我关于工作方向的,有问我关于offer选择的,有问我在项目开发中遇到的实际问题的...我自己本身工作很忙,但是一想到如果我当时遇到困难能有一位前辈帮我指引该多么幸运啊,所以遇到一些我刚好知道的问题就随手回......
  • 【Azure Function App】Java Function部署到Azure后出现中文显示乱码问题
    问题描述JavaFunction在Azure上遇见中文显示乱码问题?如何解决呢? 问题解答中文字符显示为乱码,这个情况就是服务实例上设置的编码格式不是统一的UTF-8所导致的。在查看AzureAppService/FunctionApp的官方文档,都没有明确的说明它们使用的默认编码是什么,通过询问ChatGPT-4,也没有得......
  • HJ36 字符串加密
    1.题目读题HJ36 字符串加密  这道题的意思是让您使用一种加密技巧,把一个字符串转换成另一个字符串。这种加密技巧的原理是这样的:首先,您需要选择一个单词作为密钥,比如TRAILBLAZERS。然后,您需要把这个单词中重复的字母去掉,只保留第一个出现的字母,比如TRAILBZES。接着......
  • 剑指 Offer 20. 表示数值的字符串
    题目:#遇到数字:一定合法#遇到'.'且合法需要满足条件:之前没出现过'.',之前没出现过'e'#遇到'e'且合法需要满足条件:之前没出现过'e',之前出现过整数#遇到'+'或者'-'且合法需要满足条件:位于字符串第一位,或者紧跟在'e'之后classSolution{public:boolisNumber(st......
  • 【Azure Function App】Java Function部署到Azure后出现中文显示乱码问题
    问题描述JavaFunction在Azure上遇见中文显示乱码问题?如何解决呢? 问题解答中文字符显示为乱码,这个情况就是服务实例上设置的编码格式不是统一的UTF-8所导致的。在查看AzureAppService/FunctionApp的官方文档,都没有明确的说明它们使用的默认编码是什么,通过询问ChatGPT-4,也......
  • tcp/ip 面试问题总结
    tcp三次握手为什么三次典型场景:1客户端对服务器说:大哥你好这是我的窗口大小,以及初始序号2服务器对客户端说:好的老弟,这是我的窗口大小和初始序号3客户端对服务器说:好的大哥......