📅  最后修改于: 2023-12-03 15:36:33.867000             🧑  作者: Mango
Rabin Karp 算法是一种基于哈希的字符串匹配算法,它可以用来快速判断一个字符串是否包含另一个字符串,并且可以以 $O(n+m)$ 的时间复杂度计算出所有匹配的子串。
假设我们要寻找字符串 $S$ 中是否包含字符串 $T$。我们可以将 $T$ 的哈希值计算出来,然后在 $S$ 中依次计算每个长度为 $|T|$ 的子串的哈希值,如果找到了一个哈希值相等的子串,就判断它们是否真的相等。
我们可以用一个滑动窗口来依次计算字符串 $S$ 中的子串哈希值。假设当前窗口的子串为 $S[i..i+|T|-1]$,则窗口向右移动一格时,对应的子串为 $S[i+1..i+|T|]$,其哈希值可以通过以下公式计算:
$$ hash(S[i+1..i+|T|]) = (hash(S[i..i+|T|-1]) - S[i] * b^{|T|-1}) * a + S[i+|T|] $$
其中,$a$ 和 $b$ 是两个随机数,通常取 $a = 26$,$b$ 取一个大素数。需要特别注意的是,为了避免哈希冲突,我们一般还需要对计算结果取模。
下面给出使用 Python 实现 Rabin Karp 算法的代码:
def rabin_karp(S, T):
n, m = len(S), len(T)
p = 10**9 + 7
a = 26
b = pow(a, m, p)
thash = sum(hash(T[i]) * pow(a, m-i-1, p) for i in range(m)) % p
shash = sum(hash(S[i]) * pow(a, m-i-1, p) for i in range(m)) % p
if shash == thash and S[:m] == T:
yield 0
for i in range(n - m):
shash = (shash - hash(S[i]) * b % p) * a % p + hash(S[i+m]) % p
if shash == thash and S[i+1:i+m+1] == T:
yield i + 1
在上面的代码中,我们将 $a$ 取为 26,$b$ 取为 $10^9 + 7$,这是一个非常大的素数,可以减小哈希冲突的概率。需要特别注意的是,字符串的哈希值需要使用一个较大的整数类型来存储,例如 Python 中的 int 类型。
下面是一个使用示例,输入两个字符串 S 和 T,输出 S 中所有包含 T 的子串的起始位置:
S = "ababcabcabababd"
T = "ababd"
for pos in rabin_karp(S, T):
print(pos)
输出结果为:
10
这说明在字符串 S 中,以第 10 个字符开始,包含子串 T。