重复子串模式
字数 995 2025-11-03 20:30:43
重复子串模式
题目描述
给定一个字符串 s,检查它是否可以通过由其一个子串重复多次构成。例如,字符串 "abab" 可以由子串 "ab" 重复两次构成,返回 true;而字符串 "aba" 无法通过重复某个子串构成,返回 false。
解题过程
-
问题分析
我们需要判断字符串s是否由某个子串重复多次构成。关键点在于:- 如果
s可以由子串t重复k次构成(k >= 2),那么s的长度一定是t长度的整数倍。 - 将两个
s连接在一起形成新字符串s2,并去掉首尾字符后,如果s仍然是s2的子串,则说明s满足重复子串模式。
- 如果
-
哈希思路
使用滚动哈希(Rabin-Karp 算法思想)来高效判断子串匹配。我们可以计算s的哈希值,并在双倍字符串中寻找匹配,避免逐个字符比较。 -
具体步骤
- 设字符串
s的长度为n。 - 将
s与自身连接,得到新字符串s2 = s + s,然后去掉s2的首尾字符(即取s2[1 : 2*n-1]),得到字符串s2_sub。 - 在
s2_sub中查找是否包含子串s。如果包含,则返回 true;否则返回 false。 - 使用滚动哈希优化子串查找过程:
- 选择基数
base和模数mod(例如base=131,mod=10^9+7)。 - 计算
s的哈希值target_hash。 - 计算
s2_sub的滚动哈希,并在滑动窗口中比较哈希值是否相等(需处理哈希冲突)。
- 选择基数
- 设字符串
-
示例
- 以
s = "abab"为例:n = 4,s2 = "abababab",s2_sub = "bababa"。- 在
"bababa"中查找"abab",发现包含(从索引 1 开始匹配),返回 true。
- 以
s = "aba"为例:n = 3,s2 = "abaaba",s2_sub = "baab"。"baab"中不包含"aba",返回 false。
- 以
-
复杂度分析
- 时间复杂度:滚动哈希可在 O(n) 时间内完成匹配。
- 空间复杂度:O(1)(除存储字符串外)。
关键点
- 双倍字符串去首尾的技巧将问题转化为子串匹配。
- 滚动哈希避免逐个字符比较,提升效率。