LeetCode 459. Repeated Substring Pattern
问题描述
给定一个非空的字符串 s,检查是否可以通过由它的一个子串重复多次构成。
解题思路
如果字符串 s 可以由子串 p 重复 k 次构成,那么 s 的长度 n 必定是子串长度 len(p) 的整数倍,即 len(p) 是 n 的因数。
因数枚举法
找出所有可能的子串长度:
- 一个子串如果可以重复构成整个字符串,其长度必然是字符串总长度
n的一个因数 - 遍历
1到n/2,收集所有n的因数(子串长度不可能超过n/2,因为至少要重复两次)
- 一个子串如果可以重复构成整个字符串,其长度必然是字符串总长度
逐个验证:
- 对于每个因数
factor(可能的子串长度):- 计算重复次数
count = n / factor - 截取前
factor个字符作为候选子串sub - 使用
sub.repeat(count)生成重复字符串,与原始字符串s比较 - 如果相等,返回
true
- 计算重复次数
- 对于每个因数
返回结果:如果所有因数都无法匹配,返回
false。
举例说明
以输入 s = "abab"(n=4)为例:
- 因数有:
[1, 2] - 检查 factor=1:
sub = "a",重复 4 次得"aaaa"≠"abab",不匹配 - 检查 factor=2:
sub = "ab",重复 2 次得"abab"="abab",匹配,返回true
以输入 s = "abcabcabc"(n=9)为例:
- 因数有:
[1, 3](4 不是因数,跳过) - factor=1:
"a"重复 9 次 ≠ 原串 - factor=3:
"abc"重复 3 次 = 原串,返回true
为什么枚举因数可行?
如果子串长度不是总长度的因数,则无论如何重复都无法正好拼接成原字符串。因此只需要检查所有因数长度的子串即可覆盖所有可能的解,这是一种高效的剪枝策略。
复杂度分析
- 时间复杂度:O(n * d(n)),其中 d(n) 是 n 的因数个数。对于每个因数,需要进行一次字符串拼接和比较,耗时 O(n)。在最坏情况下 d(n) 约等于 O(√n),总时间复杂度约为 O(n√n)。
- 空间复杂度:O(n),需要存储拼接后的字符串进行比较。
代码
1 | package code.J459; |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 𝒞𝒶𝓃𝒶𝓇𝓎!