字母异位词(Anagram)是指由相同字母重新排列组合形成的不同单词或短语。比如"listen"和"silent"就是一组典型的字母异位词。在实际开发中,处理字符串匹配问题时经常会遇到这类需求。
给定一个字符串s和一个非空字符串p,我们需要找到s中所有是p的字母异位词的子串,返回这些子串的起始索引。例如:
解决这类字符串匹配问题的经典方法是滑动窗口(Sliding Window)算法。该算法通过维护一个固定大小的窗口在字符串上滑动,高效地检查所有可能的子串。
滑动窗口算法的优势在于:
初始化哈希表:
设置窗口指针:
滑动窗口过程:
python复制from collections import defaultdict
def findAnagrams(s: str, p: str) -> List[int]:
if len(s) < len(p):
return []
p_count = defaultdict(int)
window_count = defaultdict(int)
# 初始化p的字符计数
for char in p:
p_count[char] += 1
result = []
left = 0
for right in range(len(s)):
# 添加当前字符到窗口
window_count[s[right]] += 1
# 当窗口大小等于p的长度时开始比较
if right - left + 1 == len(p):
if window_count == p_count:
result.append(left)
# 移动左指针,移除最左边的字符
window_count[s[left]] -= 1
if window_count[s[left]] == 0:
del window_count[s[left]]
left += 1
return result
对于仅包含小写字母的情况,可以用长度为26的数组代替哈希表,提升效率:
python复制def findAnagrams(s: str, p: str) -> List[int]:
if len(s) < len(p):
return []
p_count = [0] * 26
window_count = [0] * 26
for char in p:
p_count[ord(char) - ord('a')] += 1
result = []
left = 0
for right in range(len(s)):
window_count[ord(s[right]) - ord('a')] += 1
if right - left + 1 == len(p):
if window_count == p_count:
result.append(left)
window_count[ord(s[left]) - ord('a')] -= 1
left += 1
return result
可以引入一个match变量来记录匹配的字符数,避免每次全量比较哈希表:
python复制def findAnagrams(s: str, p: str) -> List[int]:
if len(s) < len(p):
return []
p_count = [0] * 26
window_count = [0] * 26
for char in p:
p_count[ord(char) - ord('a')] += 1
match = 0
result = []
for i in range(len(s)):
# 右指针移动
char = s[i]
idx = ord(char) - ord('a')
if p_count[idx] > 0:
window_count[idx] += 1
if window_count[idx] == p_count[idx]:
match += 1
# 左指针移动条件
if i >= len(p):
left_char = s[i - len(p)]
left_idx = ord(left_char) - ord('a')
if p_count[left_idx] > 0:
if window_count[left_idx] == p_count[left_idx]:
match -= 1
window_count[left_idx] -= 1
# 检查匹配
if match == len(set(p)):
result.append(i - len(p) + 1)
return result
在实际测试中(字符串长度100万):
当p中存在重复字母时(如p="aab"),算法需要正确处理重复计数
常见错误:窗口大小不等于p的长度时就进行比较
解决方法:严格保证比较时right - left + 1 == len(p)
常见错误:移动左指针时未正确更新哈希表
解决方法:先减计数,再检查是否为0决定是否删除键
如果需要同时查找多个模式的异位词,可以考虑:
引入容错机制,允许少量字符不匹配:
当字符串特别长时(如GB级别):