一道AC自动机模板题,唯一需要注意的是注意判重。可以用一个map<string,int>将字符串映射到其编号,最后遍历统计一遍即可。
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <map>
#include <string>
using namespace std;
#define M 10010
const int sigma=26;
string text,p[M];
int ch[60*M][sigma],val[60*M],vis[M];
int sz,n;
map<string,int> ms;
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
memset(vis,0,sizeof(vis));
}
int idx(char c){return c-'a';}
void insert(string T,int v)
{
int u=0,l=T.size();
for(int i=0;i<l;i++)
{
int c=idx(T[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;
}
int f[M*60],last[M*60];
void out(int j)
{
if(j)
{
if(!vis[val[j]])
{
vis[val[j]]=1;
}
out(last[j]);
}
}
void find(string T)
{
int l=T.size(),j=0;
for(int i=0;i<l;i++)
{
int c=idx(T[i]);
while(j&&!ch[j][c]) j=f[j];
j=ch[j][c];
if(val[j]) out(j);
else if(last[j]) out(last[j]);
}
}
void getfail()
{
queue<int> q;
f[0]=0;
for(int i=0;i<sigma;i++)
{
int u=ch[0][i];
if(u)
{
f[u]=0;
q.push(u);
last[u]=0;
}
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int i=0;i<sigma;i++)
{
int u=ch[r][i];
if(!u) continue;
q.push(u);
int v=f[r];
while(v&&!ch[v][i]) v=f[v];
f[u]=ch[v][i];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
int main()
{
freopen("in.txt","r",stdin);
int T;
cin>>T;
while(T--)
{
init();ms.clear();
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>p[i];
insert(p[i],i);
ms[p[i]]=i;
}
getfail();
cin>>text;
find(text);
int ans=0;
for(int i=1;i<=n;i++)
if(vis[ms[p[i]]]) ans++;
cout<<ans<<endl;
}
return 0;
}