uva 11019 Matrix Matcher (ac自动机二维匹配)

来源:互联网 发布:软件下载免费 编辑:程序博客网 时间:2024/05/17 05:02

题目:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1960

题意:求模式矩阵M在文本矩阵T出现的次数。

分析:将模式矩阵每行当模式串并建ac自动机,然后在T中的各行逐一匹配,找到M中每一行的所有匹配点。用二维数组c[i][j]记录以(i,j)为左上角、与M等大的矩阵中有多少个完整的行与M对应的位置匹配。如果c[i][j]==M的行数,那么(i,j)对答案的贡献+1。

代码:

#include <iostream>#include <cstring>#include <cstdio>#include <queue>#include <vector>using  namespace std;const int maxn = 1e5+6;const int kd = 26;const int sz = 1006;struct trie{int son[maxn][kd],fail[maxn];vector <int > pos[maxn];int cnt,root;int cot[sz][sz];int newnode(){fill(son[cnt],son[cnt]+kd,-1);//pos[cnt]=-1;pos[cnt].clear();return cnt++;}void Init(){cnt=0;root=newnode();memset(cot,0,sizeof(cot));}void Insert(char str[],int id){int index,now=root,i;for(i=0;str[i];i++){index=str[i]-'a';if(son[now][index]==-1)son[now][index]=newnode();now=son[now][index];}pos[now].push_back(id);//pos[now]=id;}void findfail(){queue <int > q;int i,now;fail[root]=root;for(i=0;i<kd;i++)if(son[root][i]==-1)son[root][i]=root;else{fail[son[root][i]]=root;q.push(son[root][i]);}while(!q.empty()){now=q.front();q.pop();for(i=0;i<kd;i++)if(son[now][i]==-1)son[now][i]=son[fail[now]][i];else{fail[son[now][i]]=son[fail[now]][i];q.push(son[now][i]);}}}void work(char str[],int id,int Len){int i,index,now=root,temp;for(i=0;str[i];i++){index=str[i]-'a';now=son[now][index];temp=now;while(temp!=root){for(const auto &it:pos[temp])if(id-it>=0)cot[id-it][i+1-Len]++;temp=fail[temp];}}}void solve(int N,int M,int x){int ans=0;for(int i=0;i<N;i++)for(int j=0;j<M;j++)if(cot[i][j]==x)ans++;printf("%d\n",ans);}}ac;char str[sz][sz],s[sz];int main(){int ncase,N,M,X,Y,i,j;scanf("%d",&ncase);while(ncase--){scanf("%d%d",&N,&M);for(i=0;i<N;i++)scanf("%s",str[i]);scanf("%d%d",&X,&Y);ac.Init();for(i=0;i<X;i++){scanf("%s",s);ac.Insert(s,i);}ac.findfail();for(i=0;i<N;i++)ac.work(str[i],i,Y);ac.solve(N,M,X); } return 0;} 


0 0
原创粉丝点击