再次我推荐touzani的专栏的那篇文章。虽然说和算法导论上面的是一样的,但是我还是没心情看那本黑书,密密麻麻的都是字,还是看网上的爽点。
下面我摘抄点重点的部分来帮助理解吧。
其中的
h =
d m
-1 (mod
q)
但是加入模q后,由ts ≡ p (mod q)不能说明 ts = p. 但ts � p (mod q), 可以说明 ts ≠ p,
因此当
ts
≡ p (mod q)时, 再用朴素的字符串匹配算法验证
ts =
p
。. 如果q足够大,可以期望伪命中很少出现。
算法
RABIN-KARP-MATCHER(T, P, d, q)
1 n ← length[T]
2 m ← length[P]
3 h ← dm-1 mod q
4 p ← 0
5 t0← 0
6 for i ← 1 to m � Preprocessing.
7 do p ← (dp + P[i]) mod q
8 t0← (dt0 + T[i]) mod q
9 for s ← 0 to n - m � Matching.
10 do if p = ts
11 then if P[1 ‥ m] = T [s + 1 ‥ s + m]
12 then print "Pattern occurs with shift" s
13 if s < n - m
14 then ts+1← (d(ts - T[s + 1]h) + T[s + m + 1]) mod q
C++代码:
void Rabin_Karp(char*T,char* W,int d,int q )
{
//搜索W在T中的位置
//参数d:字母表的进制,即字母表的元素个数
//参数q:一个比较大的素数,只需d*q<字长
int n=strlen(T);
int m=strlen(W);
if(n<m) return;
int i;
__int64 h=1;
for(i=1; i<=m-1; i++) //计算h
h=(h*d)%q;
__int64 w=0,t=0;
//预处理,计算P,t0
for(i=0; i<m; i++)
{
w=((d*w+W[i])%q);
t=((d*t+T[i])%q);
}
int s;
for(s=0; s<n-m+1; s++) //匹配
{
if(w==t)
{
for(i=0; i<m; i++) //进一步验证
{
if(W[i]!=T[s+i])
break;
}
if(i==m)
{
nCount++;
}
}
if(s<n-m)
t=(d*(t-T[s]*h)+T[s+m])%q; //计算ts+1
}
}