字符串匹配:RK 算法,暴力匹配算法的优化

RK 算法的全称叫 Rabin-Karp 算法,是由它的两位发明者 Rabin 和 Karp 的名字来命名的。

暴力匹配算法(Brute Force)

我们假设主串长度为n,模式串长度m,暴力匹配的时间复杂度为O(n*m)。当主串特别长的时候,匹配效率不够高。
暴力匹配过程

RK 算法:哈希算法的应用

我们知道,哈希算法是可以将任意数据转换成一组固定长度的二进制串,所以,我们可以将主串中所有与模式串长度相同的子串的哈希值计算出来,匹配时,首先比较模式串与子串的哈希值。

考虑存在哈希冲突的情况,在匹配到相同哈希值的子串后,还需要进行字符比较,我们将大量的匹配交给了哈希值比较,而计算哈希值和哈希值的比较都是很高效的,因此,效率大大高于暴力匹配法。
字符串匹配:RK 算法,暴力匹配算法的优化_第1张图片

哈希算法的设计

假设我们要匹配的主串只包含[a-z]的小写字母,可以类比十进制数的表示方法,将这些小写字母转换成 26 进制。

1874 = 1x103+8x102+7x101+4x100

bcd ==> 1x262+2x261+3x260 = 706

在计算哈希值时,可以通过前一个子串简单计算得到当前子串的哈希值:
字符串匹配:RK 算法,暴力匹配算法的优化_第2张图片
公式:

h[i] = 26*(h[i-1]-26^(m-1)*(s[i-1]-'a')) + (s[i+m-1]-'a');

其中, h[i]、h[i-1] 分别对应 s[i] 和 s[i-1] 两个子串的哈希值

时间复杂度分析

假设主串长度为n,模式串长度为m
RK 算法匹配时,分为两步:

  1. 计算n-m+1个子串的哈希值和模式串的哈希值
  2. 遍历比较子串哈希值和模式串哈希值

第一步中,时间复杂度为 O(n)。
第二步中,哈希值之间的比较时间复杂度为 O(1),因此比较 n-m+1 次,时间复杂度为 O(n)。

综上:RK 算法整体时间复杂度为O(n)

注意要点

  1. 当模式串长,计算得到的哈希值超过整数存储范围时,如何处理?
    前文中,我们设计的哈希算法是不存在哈希冲突的,因此,可以允许存在哈希冲突,从而减小哈希值的范围。
    例如,可以将字符串对应值直接相加:bcd ==> 1+2+3=6,这必定会导致严重散列冲突。可以采用其他方法,以达到效率和冲突的平衡。

  2. 存在散列冲突时,如何处理?
    当匹配到哈希值相同的子串时,由于存在散列冲突,因此不能保证该子串与模式串完全一样,我们需要进一步比较子串与模式串的字符,从而确定是否匹配成功。

你可能感兴趣的:(算法与数据结构原理详解)