哈希标记取代(KMP和AC自动机)poj3690

来源:互联网 发布:sql注入实例代码 编辑:程序博客网 时间:2024/05/16 03:46
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#include<iostream>#include<algorithm>#include<stack>#include<queue>#include<vector>#include<set>#include<map>#include<string>using namespace std;typedef long long ll;typedef unsigned long long ull;const ll INFF=0x3f3f3f3f3f3f3f3f;const int INF=0x3f3f3f3f;int n,m,T,p,q;char str[1001][1001];char mapp[101][1001][1001];ull Hash[1001][1001],temp[1001][1001];const ull b1=9973,b2=1e8+7;void get_hash(char s[1001][1001],int N,int M){    ull t=1;    for(int i=1;i<=q;i++)//最好不要用快速幂,可能会出问题,因为他利用的是unsigned long long 的自然溢出        t*=b1;    for(int i=0;i<N;i++)//先求横向hash存放于temp    {        ull e=0;        for(int j=0;j<q;j++)            e=e*b1+s[i][j];        for(int j=0;j+q<=M;j++)        {            temp[i][j]=e;            if(j+q<M)            {                e=e*b1+s[i][j+q]-s[i][j]*t;            }        }    }    t=1;    for(int i=1;i<=p;i++)        t*=b2;    for(int j=0;j+q<=M;j++)//求纵向hash    {        ull e=0;        for(int i=0;i<p;i++)            e=e*b2+temp[i][j];        for(int i=0;i+p<=N;i++)        {            Hash[i][j]=e;            if(i+p<N)            {                e=e*b2+temp[i+p][j]-temp[i][j]*t;            }        }    }}int solve(){    multiset<ull> s;    for(int i=0;i<T;i++)    {        get_hash(mapp[i],p,q);        s.insert(Hash[0][0]);//是两个0是因为求哈希时只有!!!   0+p<=p,o+q<=q    !!!    }    get_hash(str,n,m);    for(int i=0;i+p<=n;i++)        for(int j=0;j+q<=m;j++)        s.erase(Hash[i][j]);    return T-s.size();}int main(){    int ca=1;    while(1)    {        scanf("%d%d%d%d%d",&n,&m,&T,&p,&q);        if(!(n+m+T+p+q))            break;        for(int i=0;i<n;i++)            scanf("%s",str[i]);        for(int i=0;i<T;i++)            for(int j=0;j<p;j++)                scanf("%s",mapp[i][j]);        printf("Case %d: %d\n",ca++,solve());    }    return 0;}

0 0