字符串匹配之Rabin-Karp

    再次我推荐touzani的专栏的那篇文章。虽然说和算法导论上面的是一样的,但是我还是没心情看那本黑书,密密麻麻的都是字,还是看网上的爽点。

    下面我摘抄点重点的部分来帮助理解吧。

http://p.blog.csdn.net/images/p_blog_csdn_net/touzani/303255/o_image006.jpg

其中的 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
}
}

 

 

你可能感兴趣的:(字符串)