<span style="font-size:18px;">//题目链接:http://poj.org/problem?id=3690
//复杂度:如果一一检查,会退化为O(mn) 不同字符串哈希值冲突的概率非常低,
//通常可以忽视,实际不做朴素的检查,所以是O(m+n)。
//哈希函数:H(C)=(c1*pow(b,m-1)+c2*pow(b,m-2)+c3*pow(b,m-3)+...+cm*pow(b,0))mod h.(b为哈希的基数)
//递推:H(S[k+1...k+m])=( H(S[k...k+m-1])*b-sk*pow(b,m)+sk+m )mod h
//取h=pow(2,64),用自然溢出省去模运算
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
typedef unsigned long long ull;
const int maxn=1005,maxt=105;
const ull b1=9973,b2=100000007;
ull tmp[maxn][maxn],Hash[maxn][maxn];
char field[maxn][maxn],model[maxt][maxn][maxn];
multiset<ull> mul;
int P,Q;
void solve(char M[maxn][maxn],int r,int c)
{
int i,j;
ull t=1,e;
for(i=0;i<Q;i++)t*=b1;
for(i=0;i<r;i++)
{
e=0;
for(j=0;j<Q;j++)
{
e=e*b1+M[i][j];
}
for(j=0;j+Q<=c;j++)
{
tmp[i][j]=e;
if(j+Q<c)
{
e=e*b1-M[i][j]*t+M[i][j+Q];
}
}
}
t=1;
for(i=0;i<P;i++)t*=b2;
for(i=0;i<c-Q+1;i++)
{
e=0;
for(j=0;j<P;j++)
{
e=e*b2+tmp[j][i];
}
for(j=0;j+P<=r;j++)
{
Hash[j][i]=e;
if(j+P<r)
{
e=e*b2-tmp[j][i]*t+tmp[j+P][i];
}
}
}
}
int main()
{
int N,M,T,i,j,kase=1;
while(scanf("%d%d%d%d%d",&N,&M,&T,&P,&Q)!=EOF)
{
mul.clear();
if(N==0 && M==0 && T==0 && P==0 && Q==0)break;
getchar();
for(i=0;i<N;i++) scanf("%s",field[i]);
for(i=0;i<T;i++)
{
getchar();
for(j=0;j<P;j++)
{
scanf("%s",model[i][j]);
}
}
for(i=0;i<T;i++)
{
solve(model[i],P,Q);
mul.insert(Hash[0][0]);
}
solve(field,N,M);
for(i=0;i<N-P+1;i++)
{
for(j=0;j<M-Q+1;j++)
{
mul.erase(Hash[i][j]);
}
}
printf("Case %d: %d\n",kase++,T-mul.size());
}
return 0;
}
</span>
字符创匹配(Rabin-Karp 算法)(hash)
最新推荐文章于 2021-06-28 16:00:51 发布