String Matching, Karp-Rabin
Last updated
Last updated
给定两个字符串 s 和 t,判断 s 是否是 t 的子串?如果是,出现在哪?出现了多少次?
子串比较的复杂度: ,因此算法时间复杂度为 ,近似为
在 Naive Algorithm 中,我们每次比较子串的复杂度都是 ,但实际上,前后两次比较中,即 与 ,两个 t 的子串有 个字母是重复的,如果能够不用重复比较这些比较过的字母,就有可能将比较子串的复杂度将到 。
于是 Rolling Hash ADT 诞生了:它维护一个字符串 x,同时提供以下三个方法
分析:
如果 Rolling Hash ADT 能够做到:
Karp-Rabin Algorithm 的算法复杂度就是:
想象 string x 是一个基数(base)为 a 的多位数(multi-digit number)u :
在实际问题中 a 就是所有可能的字符数量。
两个不同的子串的哈希值相等的概率 <
方法
基本实现
优化实现
r()
,其中 p 是接近 |s| 的随机质数,r 中保存着 u 和 x
,其中 p 是接近 |s| 的随机质数, r 中保存着 和 ,而并非 u
r.append(c)
即
r.skip(c)
即
方法
功能
r()
r 就是 hash function,r() 返回当前子串的哈希值 h(x)
r.append(c)
将字母 c 放到 x 的末尾
r.skip(c)
将 x 的第一个字母移除