AC自动机(矩阵匹配)uva11019

来源:互联网 发布:陈意涵用的跑步软件 编辑:程序博客网 时间:2024/05/29 02:51

Problem H
Matrix Matcher
Input:
Standard Input

Output: StandardOutput

 

Given an N * M matrix, your task is to find the number of occurences of an X * Y pattern.

 

Input

The first line contains a singleinteger t(t ≤ 15), the number of test cases.

 

For each case, the first linecontains two integers N and M (N, M ≤ 1000). The next N lines contain Mcharacters each.

 

The next line contains twointegers X and Y (X, Y ≤ 100). The next X lines contain Y characterseach. 

 

Output

For each case, output a singleinteger in its own line, the number of occurrences.

 

SampleInput                               Output for SampleInput

2
1 1
x
1 1
y
3 3
abc
bcd
cde
2 2
bc
cd

0

2

 


找出P在T中出现了多少次

先把P的每一行作为模式串构造AC自动机,然后在T中逐行匹配。用一个cnt[r][c]表示T中以(r,c)为左上角,与P等大的矩阵中有多少个完整地行和P对应位置的航完全一样。那么cnt[r][c]==x的就是答案

#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=105;const int maxm=maxn*maxn;const int SIGMA_SIZE=26;int n,m,x,y,ans;char T[maxn*10][maxn*10],P[110][110];int repr[maxn],next[maxn],len[maxn];int cnt[maxn*10][maxn*10];void process(int pos,int pnum,int tnum){    int r=repr[pnum-1],c=pos-len[r]+1;    while(r>=0)    {        if(tnum>=r)            cnt[tnum-r][c]++;        r=next[r];    }}struct AC{    int ch[maxm][26],val[maxm];    int fail[maxm],last[maxm];    int sz;    void clear(){memset(ch[0],0,sizeof(ch[0]));sz=1;}    int idx(char x){return x-'a';}    void insert(char *s,int id)    {        int n=strlen(s);        int u=0;        for(int i=0;i<n;i++)        {            int c=idx(s[i]);            if(!ch[u][c])            {                memset(ch[sz],0,sizeof(ch[sz]));                val[sz]=0;                ch[u][c]=sz++;            }            u=ch[u][c];        }        val[u]=id;    }    void getfail()    {        queue<int> q;        int u=0;        fail[0]=0;        for(int c=0;c<SIGMA_SIZE;c++)        {            u=ch[0][c];            if(u){fail[u]=last[u]=0;q.push(u);}        }        while(!q.empty())        {            int r=q.front();q.pop();            for(int c=0;c<SIGMA_SIZE;c++)            {                u=ch[r][c];                if(!u){ch[r][c]=ch[fail[r]][c];continue;}                q.push(u);                int v=fail[r];                while(v&&!ch[v][c])v=fail[v];                fail[u]=ch[v][c];                last[u]=val[fail[u]]?fail[u]:last[fail[u]];            }        }    }    void find(char *s,int id)    {        int u=0;        int n=strlen(s);        for(int i=0;i<n;i++)        {            int c=idx(s[i]);            u=ch[u][c];            int temp=0;            if(val[u])temp=u;            else if(last[u])temp=last[u];            while(temp)            {                process(i,val[temp],id);                temp=last[temp];            }        }    }}ac;int main(){    int cas;    scanf("%d",&cas);    while(cas--)    {        ac.clear();        scanf("%d%d",&n,&m);        for(int i=0;i<n;i++)scanf("%s",T[i]);        scanf("%d%d",&x,&y);        for(int i=0;i<x;i++)        {            scanf("%s",P[i]);            repr[i]=i;            next[i]=-1;            len[i]=strlen(P[i]);            for(int j=0;j<i;j++)            {                if(!strcmp(P[j],P[i]))                {                    repr[i]=j;                    next[i]=next[j];                    next[j]=i;                    break;                }            }            if(repr[i]==i)ac.insert(P[i],i+1);        }        ac.getfail();        memset(cnt,0,sizeof(cnt));        ans=0;        for(int i=0;i<n;i++)            ac.find(T[i],i);        for(int i=0;i<n-x+1;i++)            for(int j=0;j<m-y+1;j++)                if(cnt[i][j]==x)ans++;        printf("%d\n",ans);    }    return 0;}




0 0