题目的大意是对于给定的文本串和模板串,要求出模板串在文本串中出现的次数,那么很显然可以先对模板串一行一行的进行构建Trie树,而后对于文本串也一行一行的进行匹配寻找,在寻找的过程中对相应的行列进行记录就可以了,其中要注意的是模板串中可能重复字符串,即不同行的字符串相同,因而要另设一数组进行相应的记录,妥妥的一道AC自动机题。
值得一提的是本题可以用Hash的思想去做,并且时间复杂度可以降到50ms(AC自动机的时间复杂度达到2000+ms),但其构造过程比较奇特,博主自己的Hash也不是很会- -.....有兴趣得可以到VJUDGE上搜索题目后看LeaderBoad,代码是公开的。
下面是AC自动机的代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
char ax[1005][1005],ac[105][105];
int cnt[1005][1005],N,M,X,Y;
const int maxn=105*105;
int Next[maxn][27],fail[maxn],value[maxn],last[maxn],My[maxn];
struct Trie
{
int L,root;
int getNewnode()
{
for(int i=0;i<26;i++)
Next[L][i]=0;
value[L++]=0;
return L-1;
}
void init()
{
memset(cnt,0,sizeof(cnt));
memset(My,0,sizeof(My));
L=0;
root=getNewnode();
return ;
}
void Insert(char* s,int id)
{
int p=root;
int len=strlen(s);
for(int i=0;i<len;i++)
{
int ad=s[i]-'a';
if(Next[p][ad]==0)
Next[p][ad]=getNewnode();
p=Next[p][ad];
}
if(value[p])
My[id+1]=value[p];
value[p]=id+1;
}
void build()
{
fail[root]=root;
queue<int> q;
for(int i=0;i<26;i++)
{
int u=Next[0][i];
if(u)
{
fail[u]=0;
last[u]=0;
q.push(u);
}
}
while(!q.empty())
{
int p=q.front();
q.pop();
for(int i=0;i<26;i++)
{
int temp=Next[p][i];
if(!temp)
{
Next[p][i]=Next[fail[p]][i];
continue;
}
q.push(temp);
int v=fail[p];
while(v&&!Next[v][i])
v=fail[v];
fail[temp]=Next[v][i];
last[temp]=value[fail[temp]]?fail[temp]:last[fail[temp]];
}
}
}
void print(int x,int y,int j)
{
if(j)
{
if(x-value[j]+1>=0)
cnt[x-value[j]+1][y]++;
int t =value[j];
while(My[t])
{
t=My[t];
if(x-t+1>=0)
cnt[x-t+1][y]++;
}
print(x,y,last[j]);
}
}
void find1(char* s,int r)
{
int p=root;
int len=strlen(s);
for(int i=0;i<len;i++)
{
int x=s[i]-'a';
p=Next[p][x];
if(value[p])
print(r,i,p);
else if(last[p])
print(r,i,last[p]);
}
}
}AC;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int ans=0;
AC.init();
scanf("%d%d",&N,&M);
for(int i=0;i<N;i++)
scanf("%s",&ax[i]);
scanf("%d%d",&X,&Y);
for(int i=0;i<X;i++)
{
scanf("%s",&ac[i]);
AC.Insert(ac[i],i);
}
AC.build();
for(int i=0;i<N;i++)
AC.find1(ax[i],i);
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;
}