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 |
下面的字符矩阵在上面的字符矩阵中出现了多少次。
把模版矩阵一行一行加入AC自动机后,文本矩阵一行一行匹配。cnt[i][j]表示左上角坐标i,j,大小和模版矩阵P相等的矩阵匹配了多少行。那么每次匹配都可以根据匹配的位置和行列关系算出对应的i,j,把这个cnt[i][j]加1。最后看有多少个cnt的值为X。
还有要注意的一个地方,模版串可能有几行是一样的,因此需要链表,匹配了模版串的某一行后和这行一样的也匹配了。
#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
#define eps 1e-9
#define MAXN 1010
#define MAXM 55
#define SIGMA_SIZE 26
#define MAXNODE MAXN*SIGMA_SIZE
#define MOD 999983
typedef long long LL;
using namespace std;
int T,N,M,X,Y,tr,len[MAXN],next[MAXN],cnt[MAXN][MAXN];
char text[MAXN][MAXN],P[MAXN][MAXN];
void process_match(int i,int j){
int r=j-1,c=i-len[r]+1;
while(r!=-1){
if(tr>=r) cnt[tr-r][c]++;
r=next[r];
}
}
struct AC{
int ch[MAXNODE][SIGMA_SIZE],f[MAXNODE],last[MAXNODE],val[MAXNODE],sz;
void init(){
memset(ch[0],0,sizeof(ch[0]));
sz=1;
}
int idx(char c){
return c-'a';
}
void insert(char *s,int v){
int u=0;
for(int i=0;s[i];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]=v;
}
void get_fail(){
queue<int> q;
f[0]=0;
for(int c=0;c<SIGMA_SIZE;c++) if(ch[0][c]){
int u=ch[0][c];
f[u]=last[u]=0;
q.push(u);
}
while(!q.empty()){
int r=q.front();
q.pop();
for(int c=0;c<SIGMA_SIZE;c++){
int u=ch[r][c];
if(!u) continue;
q.push(u);
int v=f[r];
while(v&&!ch[v][c]) v=f[v];
f[u]=ch[v][c];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
void report(int i,int j){
if(j){
process_match(i,j);
report(i,last[j]);
}
}
void find(char *T){
int j=0;
for(int i=0;T[i];i++){
int c=idx(T[i]);
while(j&&!ch[j][c]) j=f[j];
j=ch[j][c];
if(val[j]) report(i,val[j]);
else if(last[j]) report(i,val[last[j]]);
}
}
}ac;
int main(){
freopen("in.txt","r",stdin);
scanf("%d",&T);
while(T--){
ac.init();
scanf("%d%d",&N,&M);
for(int i=0;i<N;i++) scanf("%s",text[i]);
scanf("%d%d",&X,&Y);
for(int i=0;i<X;i++){
scanf("%s",&P[i]);
next[i]=-1;
len[i]=strlen(P[i]);
int flag=1;
for(int j=0;j<i;j++) if(!strcmp(P[i],P[j])){
next[i]=next[j];
next[j]=i;
flag=0;
break;
}
if(flag) ac.insert(P[i],i+1);
}
ac.get_fail();
memset(cnt,0,sizeof(cnt));
for(tr=0;tr<N;tr++) ac.find(text[tr]);
int ans=0;
for(int i=0;i<N;i++)
for(int j=0;j<M;j++) if(cnt[i][j]==X) ans++;
printf("%d\n",ans);
}
return 0;
}