RT,思路和题解一样,T的每行建AC自动机,S的每行Query一次。然后每列再KMP求一下出现次数。
这题题意就是问S这个大矩阵里,T这个小矩阵出现了多少次。
udebug 的数据过了,现在WA on 1
// Problem: UVA11019 Matrix Matcher
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/UVA11019
// Memory Limit: 0 MB
// Time Limit: 3000 ms
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
#define M 1005
#define N 105
#define NM 1000
int fal[M],T,n,m,n2,m2,o=26,aft[M][M],at[N+M],fail[M],cnp,cntp,ans,rd[M*N][30],tag[M*N],ed[M];
string s[M],t[M],ft[M];
bool cmp(string a,string b) {return a<b;}
map<string,int>idd;
queue<int>q;
void Re()//多测清空
{
memset(rd,0,sizeof(rd));
memset(tag,0,sizeof(tag));
idd.clear(),cntp=ans=cnp=0;
memset(aft,0,sizeof(aft));
memset(at,0,sizeof(at));
memset(fail,0,sizeof(fail));
}
int tn(char cc) {return (cc-'a'+1);}//小写字母转数字
void Ins(string x,int id) //平凡的建字典树
{
int now=0,len=x.length();
for(int i=0;i<len;i++)
{
if(!rd[now][tn(x[i])]) rd[now][tn(x[i])]=++cntp;
now=rd[now][tn(x[i])];
}
tag[now]=id,ed[id]=now; return;
}
void Dofail() //建Trie图/fail
{
int u;
for(int i=1;i<=o;i++) if(rd[0][i]) q.push(rd[0][i]);
while(!q.empty())
{
u=q.front(),q.pop();
for(int i=1;i<=o;i++)
{
if(rd[u][i]) fail[rd[u][i]]=rd[fail[u]][i],q.push(rd[u][i]);
else rd[u][i]=rd[fail[u]][i];
}
}
return;
}
void Query(string x,int id)
{
int now=0,len=x.length();
for(int i=0;i<len;i++)
now=rd[now][tn(x[i])],aft[id][i+1]=tag[now];
return;
}
int Done() //KMP模板
{
int j,res=0; fail[0]=0;
for(int i=1;i<=n2+n;i++)
{
j=fail[i-1];
while(j>0&&at[j]!=at[i]) j=fail[j-1];
fail[i]=j+(at[i]==at[j]);
res+=(fail[i]==n2?1:0);
}
return res;
}
int main()
{
cin>>T;
for(int i=1;i<=T;i++)
{
cin>>n>>m,Re(); for(int i=1;i<=n;i++) cin>>s[i];
cin>>n2>>m2; for(int i=1;i<=n2;i++) cin>>t[i],ft[i]=t[i];
sort(ft+1,ft+n2+1,cmp); //去重
for(int i=1;i<=n2;i++) if(ft[i]!=ft[i-1]) Ins(ft[i],++cnp),idd[ft[i]]=cnp; Dofail(); //AC自动机
for(int i=1;i<=n2;i++) at[i-1]=idd[t[i]]; //KMP的T
for(int i=1;i<=n;i++) Query(s[i],i); //每行在自动机上跑一遍
at[n2]=-1,ans=0;//-1是分隔符
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++) at[n2+j]=aft[j][i]; //弄出来要KMP的串
ans+=Done();
}
cout<<ans<<endl;
}
return 0;
}