字符串中子串重复出现位置查找的代码优化咨询
嘿,这个需求我之前也碰到过——普通的子串查找逻辑很容易漏掉重叠的匹配,刚好能给你几个实用的优化方案,完美解决你提到的例子:
方案1:手动遍历检查所有起始位置(直观易懂)
这种方法的核心是逐个检查原字符串中每一个可能的起始位置,不管之前是否找到过匹配,这样就能捕捉到重叠的子串。
def find_all_overlapping_occurrences(s, sub): sub_length = len(sub) str_length = len(s) occurrences = [] # 处理边界情况:子串为空或比原字符串长 if sub_length == 0 or sub_length > str_length: return occurrences # 遍历所有合法的起始索引(0-based) for start_idx in range(str_length - sub_length + 1): # 截取对应长度的子串对比 if s[start_idx:start_idx+sub_length] == sub: # 转换为你需要的1-based位置格式 start_pos = start_idx + 1 end_pos = start_pos + sub_length - 1 occurrences.append(f"{start_pos}-{end_pos}") return occurrences # 测试你的示例 target_str = "ABBABBABAAABBBABABAA" sub_str = "BABA" results = find_all_overlapping_occurrences(target_str, sub_str) print(", ".join(results)) # 输出:5-8, 13-16, 15-18
为什么这个方法能捕捉重叠?
比如当在起始索引12(对应1-based的13)找到"BABA"后,下一次循环会直接检查索引13,而不是跳到12+4=16,这样就能发现索引14(1-based15)开始的重叠匹配。
方案2:用正则表达式快速捕获重叠匹配(简洁高效)
如果你喜欢更简洁的代码,可以用Python的re模块配合正向先行断言,它能在不消耗字符的前提下检查后续是否有匹配,天然支持重叠查找。
import re def find_all_overlapping_occurrences_re(s, sub): sub_length = len(sub) occurrences = [] if sub_length == 0 or sub_length > len(s): return occurrences # 用正向先行断言匹配所有可能的起始位置,re.escape避免子串含正则特殊字符 pattern = re.compile(f'(?={re.escape(sub)})') for match in pattern.finditer(s): start_pos = match.start() + 1 end_pos = start_pos + sub_length - 1 occurrences.append(f"{start_pos}-{end_pos}") return occurrences # 测试示例 target_str = "ABBABBABAAABBBABABAA" sub_str = "BABA" results = find_all_overlapping_occurrences_re(target_str, sub_str) print(", ".join(results)) # 输出同样为:5-8, 13-16, 15-18
正则方法的优势
- 代码更短,逻辑更紧凑
- 当子串包含正则特殊字符(比如
.、*、?)时,re.escape()能自动转义,避免匹配出错 - 适合复杂的子串匹配场景(比如带通配符的查找)
两种方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 手动遍历 | 直观易懂,无需依赖模块 | 代码量稍多,复杂场景扩展性弱 |
| 正则表达式 | 简洁高效,支持复杂匹配 | 需要理解正则断言的概念 |
内容的提问来源于stack exchange,提问作者Emin
相关产品推荐
相关产品推荐

