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;
}