LeetCode 1668. 最大重复子字符串
题目描述


题意分析
把
word连续拼接若干次,求拼接结果能作为sequence连续子串的最大次数。子串可以从任意位置开始,但多处不相邻的出现不能合并计数;一次也找不到时返回 0。
解法:逐次扩展
核心思路
[!blue]
从一份
word开始,每次追加一份,检查整个候选串是否出现在sequence中。若连续k份不存在,更多份也不可能存在:任何更长的重复串都以这k份为前缀,它若出现,前面的k份也一定出现。因此可行次数从 1 开始连续,第一次失败就能结束。
count记录已经确认成功的重复次数。每轮追加后,缓冲区保存的是count+1份候选;只有查找成功才增加count,失败时直接返回此前的次数。这样无需扫描候选的每个起点,交给内置子串查找即可。题目保证
word非空,候选每轮都会变长。设两串长度为n、m,最多成功floor(n/m)次,再尝试一次必然失败,所以循环一定结束;两串长度都不超过 100,逐次尝试足够。
解题步骤
- 追加一份 word。
- 检查整个候选是否为 sequence 的子串。
- 成功时次数加一,失败时结束。
- 返回最后成功次数。
代码实现
class Solution {
public int maxRepeating(String sequence, String word) {
int count = 0;
StringBuilder sb = new StringBuilder();
while (true) {
// 缓冲区是下一次尝试,成功后才增加已确认次数。
sb.append(word);
if (sequence.contains(sb.toString())) {
count++;
} else {
// 当前重复次数不可行,更多次也不可能成为子串。
break;
}
}
return count;
}
}
import "strings"
func maxRepeating(sequence string, word string) int {
count := 0
cur := ""
for {
// 缓冲区是下一次尝试,成功后才增加已确认次数。
cur += word
if strings.Contains(sequence, cur) {
count++
} else {
// 当前重复次数不可行,更多次也不可能成为子串。
break
}
}
return count
}
复杂度分析
- 时间复杂度:设
q为实际尝试次数,$q\leq\lfloor n/m\rfloor+1$。第j次候选长为jm,按朴素子串查找的 $O(njm)$ 上界累加,查找总计 $O(nmq^2)$;候选构造和复制另需 $O(mq^2)$,包含在此前上界中。内置查找的实际成本可能更低。- 空间复杂度:$O(mq)$,保存候选及转换后的字符串,且 $mq\leq n+m$。
关键点总结
[!green]
- 重复串必须连续,不能把散落的多次出现相加。
- 第一次失败即可结束,不会漏掉更大的可行次数。
易错点总结
[!yellow]
- 只检查
sequence的开头会漏掉从中间位置开始的重复串,必须判断完整候选是否为子串。- 忽略最后失败的一轮,直接用缓冲区长度计算次数,会多算一次。
- 先检查空缓冲再追加,会把空串也算作一次成功。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 1566. 重复至少 K 次且长度为 M 的模式 | 简单 | 同样要求重复块连续出现,本题模式内容已知并求最大重复次数,原题模式内容由数组窗口决定。 |
| 459. 重复的子字符串 | 简单 | 原题整个串由一个模式重复构成,本题只需在较大串内部找到连续重复的目标词。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!