字符创匹配(Rabin-Karp 算法)(hash)

来源:互联网 发布:java 多线程并发教程 编辑:程序博客网 时间:2024/05/29 04:32
<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>

0 0