📅  最后修改于: 2023-12-03 15:09:22.158000             🧑  作者: Mango
在字符串处理过程中,经常需要查询字符串中包含指定子串的次数,即查询字符串范围内等于给定字符串的子集数。本文将介绍如何实现字符串范围查询。
暴力法即为对于每个可能出现的位置,逐一比较给定子串和当前位置开始的子串是否相等:
def search(s: str, p: str) -> int:
cnt = 0
for i in range(len(s) - len(p) + 1):
if s[i: i + len(p)] == p:
cnt += 1
return cnt
时间复杂度为 $O(n \cdot m)$,其中 $n$ 为字符串长度,$m$ 为给定子串长度。
KMP算法是一种字符串匹配算法,其核心思路是避免在匹配过程中进行无用的回溯操作。该算法可以预处理出一个模式串的「部分匹配表」,使用该表可以在匹配过程中快速跳过不可能匹配的位置。
def search(s: str, p: str) -> int:
m, n = len(s), len(p)
if n == 0:
return 0
# 构建部分匹配表
next = [0] * n
j = 0
for i in range(1, n):
while j > 0 and p[i] != p[j]:
j = next[j - 1]
if p[i] == p[j]:
j += 1
next[i] = j
# 匹配字符串
cnt, j = 0, 0
for i in range(m):
while j > 0 and s[i] != p[j]:
j = next[j - 1]
if s[i] == p[j]:
j += 1
if j == n:
cnt += 1
j = next[j - 1]
return cnt
时间复杂度为 $O(n + m)$,其中 $n$ 为字符串长度,$m$ 为给定子串长度。
哈希法是利用哈希函数将字符串转换为数字,避免直接比较字符串的过程。在比较时,只需比较哈希值是否相等即可。
def search(s: str, p: str) -> int:
m, n = len(s), len(p)
if n == 0:
return 0
# 计算哈希值
p_hash = sum(hash(c) for c in p)
s_hash = sum(hash(c) for c in s[:n])
cnt = int(p_hash == s_hash)
# 滑动窗口比较哈希值
for i in range(1, m - n + 1):
s_hash += hash(s[i + n - 1]) - hash(s[i - 1])
cnt += int(p_hash == s_hash)
return cnt
时间复杂度为 $O(n + m)$,其中 $n$ 为字符串长度,$m$ 为给定子串长度。
本文介绍了三种字符串范围查询的实现方法:暴力法、KMP算法和哈希法。其中,KMP算法和哈希法可以达到线性复杂度,具有较高的效率。工程实践中可以根据实际需求选择适合的算法。