📌  相关文章
📜  Rabin-Karp算法(1)

📅  最后修改于: 2023-12-03 15:34:36.388000             🧑  作者: Mango

Rabin-Karp算法

Rabin-Karp算法是一种字符串匹配算法,用于在文本串中查找词或模式串的出现位置。它利用了哈希函数的思想,将词或模式串和文本串分别哈希,然后进行比较,以此来判断它们是否匹配。

算法原理

Rabin-Karp算法的核心思想是将词或模式串和文本串分别哈希,然后进行比较。具体地,算法首先选定一个素数p作为哈希函数的基数,然后将词或模式串和文本串分别哈希到一个p进制的整数上。于是,我们只需要比较这两个整数是否相等即可判断它们是否匹配。

然而,由于哈希函数的唯一性并不能保证两个不同的字符串哈希值不同,因此需要引入一种解决冲突的方法。这里我们选择了一种比较简单但有效的方法,即滚动哈希。具体地,为了避免每次重新计算模式串哈希值,我们引入了一个常数常数d,表示p进制数的最高位的权值。这样,在匹配时,我们可以根据前一个子串和后一个子串的哈希值之间的关系来快速地计算新的哈希值,从而减少重复计算。

具体实现时,我们先将模式串和文本串的前m个字符哈希,然后逐个比较它们的哈希值。若相等,则进行进一步比较;否则,我们需要计算文本串中下一个长度为m的子串的哈希值,然后再进行比较。这样反复比较直到找到匹配的子串为止。

算法流程

Rabin-Karp算法的流程如下:

  1. 选定一个素数p作为哈希函数的基数,将模式串和文本串分别哈希到一个p进制的整数上。
  2. 用滚动哈希的方法计算文本串中第一次出现子串的哈希值,并比较它和模式串的哈希值是否相等。若相等,则进行进一步的比较;否则继续寻找文本串中下一个长度为m的子串。
  3. 如果找到了匹配的子串,则将其位置返回;否则返回-1。
算法实现

以下是Rabin-Karp算法的Python实现:

def rabin_karp(text: str, pattern: str) -> int:
    n, m = len(text), len(pattern)
    if n < m:
        return -1

    # 计算素数和模数
    prime, modulus = 101, 2 ** 32

    # 计算模式串和文本串的哈希值
    pattern_hash = sum(ord(pattern[i]) * prime ** i for i in range(m)) % modulus
    text_hash = sum(ord(text[i]) * prime ** i for i in range(m)) % modulus

    # 比较哈希值
    if text_hash == pattern_hash and text[:m] == pattern:
        return 0

    # 计算d^(m-1)的值,用于快速计算新的哈希值
    d = pow(prime, m-1, modulus)

    # 滚动哈希
    for i in range(m, n):
        text_hash = (text_hash - ord(text[i-m]) * d) % modulus
        text_hash = (text_hash * prime + ord(text[i])) % modulus
        if text_hash == pattern_hash and text[i-m+1:i+1] == pattern:
            return i-m+1

    return -1

其中,primemodulus分别表示选定的素数和模数,用于哈希。pattern_hashtext_hash代表模式串和文本串的哈希值。d表示在滚动哈希时用到的常数。在滚动哈希时,我们用到了Python的快速幂函数pow()来计算d^(m-1)的值。

算法复杂度

Rabin-Karp算法的时间复杂度取决于哈希函数的性能和哈希冲突的情况。在理想的情况下,时间复杂度为O(n+m)。然而,在最坏情况下,哈希冲突可能非常频繁,导致时间复杂度退化为O(nm)。因此,在实际应用中,我们需要选择一个好的哈希函数和合适的哈希冲突解决方法,以提高算法的效率。