leetcode459 重复的子字符串 周期性字符串问题 KMP算法

1.移动匹配法:

如果一个字符串s是周期串,则s+s的中间一定有一部分s

我们在判断 s + s 拼接的字符串里是否出现一个s的的时候,要刨除 s + s 的首字符和尾字符,这样避免在s+s中搜索出原来的s,我们要搜索的是中间拼接出来的s。

begin()返回向量头指针,指向第一个元素

end()返回向量尾指针,指向向量最后一个元素的下一个位置

t.find(s) 是 std::string 的成员函数,用于在字符串 t 中查找子串 s

std::string::npos 是一个常量,表示"未找到"或"无效位置"

cpp 复制代码
class Solution {
public:
    bool repeatedSubstringPattern(string s) {
        string t = s + s;
        t.erase(t.begin());
        t.erase(t.end()-1);
        if(t.find(s) != string::npos) return true;
        return false;
    }
};

2.KMP法:最小重复单位就是最长相等前后缀不包含的那个部分

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

其中 len(s) 为字符串 s 的长度 ,maxLen 为最长公共前后缀的长度。

如果 s 是周期串,那【s 的长度】是【s 的长度减去最长公共前后缀的长度】的倍数,那字符串 s 就是周期串。

如果是周期串,那对应位置上的字母应该是一样的,如果对应位置上的字母不一样,那就肯定不是周期串。maxLen == 0 or sn - 1 != sn - 1 - maxLen

next数组存放的元素是某个阶段上重复的元素个数,由于能组成重复元素的长串next数组一定是整体向上递增的(即使中间数字会有波动起伏),取next最后一个元素就是最长相同前后缀(即重复的元素个数,记为max),len - max就是最小重复子串长度,如果len能被最小重复字串长度整除,说明长串均可由其构成。

cpp 复制代码
class Solution {
public:
    void getNext(int* next, string s){
        int i = 1;
        int j = 0;
        for(;i<s.size();i++){
            while(j > 0 && s[j] != s[i]){
                j = next[j-1];
            }
            if(s[j]==s[i]){
                j++;
            }
            next[i] = j;
        }
    }

    bool repeatedSubstringPattern(string s) {
        if(s.size() == 0) return false;
        vector<int> next(s.size());
        getNext(&next[0], s);
        int len = s.size();
        if(next[len - 1] != 0 && len % (len - (next[len - 1])) == 0) {
            return true;
        }   
        return false;
    }
};

int nexts.size();

这种定义方式在 C++ 中是 变长数组(VLA) ,虽然在某些编译器中支持,但并不是 C++ 标准的一部分。如果 s.size() 为 0,或者 next 数组的大小不足以容纳 s.size() 个元素,就会导致未定义行为。

需要修改。

if(nextlen - 1 != 0 && len % (len - (nextlen - 1)) == 0) {

return true;

}

return false;

你提到的例子 s = "abcabcd" 非常好!它确实是一个特殊情况,可以帮助我们更深入地理解 next 数组和最长公共前后缀的关系。


1. 分析 s = "abcabcd"

  • 字符串 s = "abcabcd",长度为 7。

  • 我们手动计算它的 next 数组:

索引 (i) 前缀 s[0..i] 最长公共前后缀长度 (next[i])
0 "a" 0
1 "ab" 0
2 "abc" 0
3 "abca" 1
4 "abcab" 2
5 "abcabc" 3
6 "abcabcd" 0
  • next 数组为 [0, 0, 0, 1, 2, 3, 0]。

  • next[len - 1] = next[6] = 0。


2. 最长公共前后缀长度

  • 对于 s = "abcabcd",next[len - 1] = 0,表示整个字符串没有非平凡的最长公共前后缀。

  • 也就是说,字符串 s 的最长公共前后缀长度为 0。


3. 为什么 next[len - 1] 是最长公共前后缀长度?

  • next[len - 1] 表示前缀 s[0..len-1](即整个字符串 s)的最长公共前后缀的长度。

  • 如果 next[len - 1] = 0,说明整个字符串没有非平凡的最长公共前后缀。


4. 特殊情况分析

对于 s = "abcabcd":

  • next[len - 1] = 0,表示整个字符串没有非平凡的最长公共前后缀。

  • 因此,字符串 s 不能由某个子串重复多次构成。

所以判定条件前面也加了nextlen-1 != 0

相关推荐
倒头就睡的小比特3 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!3 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼3 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光3 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark3 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her13 天前
并查集-听课笔记
笔记·算法·并查集
码流子3 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven3 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark3 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218613 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法