基于Python实现反向搜索(Backward search)统计子串出现次数
嘿,我来帮你理清用反向搜索(Backward Search)结合zip遍历字符串来统计子串出现次数的具体思路,结合你给出的例子一步步拆解:
核心思路:反向搜索的优势
要统计子串ban的出现次数,反向搜索的核心是从子串的最后一个字符开始匹配——也就是先找n,再找a,最后找b。这种方式能更早排除不匹配的情况,尤其是结合排序后的字符串s1,可以快速缩小搜索范围,大幅提升效率。
具体实现步骤
1. 预处理目标子串
先把目标子串ban反转成nab,这样我们就可以从最后一个字符开始依次匹配:
target = 'ban' rev_target = target[::-1] # 得到 'nab'
2. 利用排序字符串s1缩小搜索范围
因为s1是s的排序版本,相同字符会集中在一起。我们可以先定位到rev_target第一个字符(也就是n)在s1中的区间,这样不用遍历整个s,只需要在这个区间内搜索即可:
original = 'panamabananas$' s = 'smnpbnnaaaaa$a' s1 = '$aaaaaabmnnnps' first_char = rev_target[0] # 找到s1中第一个'n'的位置 start_idx = s1.index(first_char) # 找到s1中最后一个'n'的位置 end_idx = len(s1) - s1[::-1].index(first_char) - 1
3. 结合遍历(或zip)完成匹配统计
这里我们可以遍历s中缩小后的区间,同时跟踪反向子串的匹配进度:
count = 0 current_match_pos = 0 # 记录当前匹配到反向子串的第几个字符 for char in s[start_idx:end_idx+1]: # 如果当前字符匹配反向子串的当前位置,推进匹配进度 if current_match_pos < len(rev_target) and char == rev_target[current_match_pos]: current_match_pos += 1 # 完全匹配反向子串,说明找到一个目标子串 if current_match_pos == len(rev_target): count += 1 current_match_pos = 0 # 重置进度,继续寻找下一个匹配 else: # 不匹配则重置进度,同时检查当前字符是否是反向子串的起始字符 current_match_pos = 0 if char == rev_target[0]: current_match_pos = 1 print(f"子串'{target}'的出现次数: {count}")
为什么用zip?
如果需要同时对比s和s1的字符(比如验证排序后的位置对应关系),可以用zip(s, s1)遍历,在遍历过程中同步获取原字符串和排序后的字符,辅助我们调整搜索区间:
# 示例:用zip遍历同时查看s和s1的对应字符 for s_char, s1_char in zip(s, s1): print(f"s中的字符: {s_char}, s1中的字符: {s1_char}")
这种方式可以让你在遍历过程中,实时参考排序后的字符分布,动态调整匹配策略。
关键优势总结
- 反向搜索减少无效匹配:从子串末尾开始匹配,能快速排除不相关的字符,避免正向搜索中“前面匹配但后面不匹配”的无效遍历。
- 排序字符串缩小范围:利用
s1的排序特性,直接定位到可能包含目标子串末尾字符的区间,大幅减少需要遍历的字符数量。
内容的提问来源于stack exchange,提问作者Joe Smith
相关产品推荐
相关产品推荐

