描述
给定 n 个长度不超过 50 的由小写英文字母组成的单词准备查询,以及一篇长为 m 的文章,问:文中出现了多少个待查询的单词。多组数据。
输入
第一行一个整数 T,表示数据组数;
对于每组数据,第一行一个整数 n,接下去 n 行表示 n 个单词,最后一行输入一个字符串,表示文章。
输出
对于每组数据,输出一个数,表示文中出现了多少个待查询的单词。
样例输入
1
5
she
he
say
shr
her
yasherhs
样例输出
3
提示
对于全部数据,1≤n≤104,1≤m≤106
#include<cstdio>//不是计算单词出现的次数,而是出现的个数
#include<cstring>
using namespace std;
const int N=1e4+5,M=1e6+5;
int t,n,ch[M][30],cnt=0,bo[M],que[M],nxt[M],ans,val[M];
char sta[M],stw[N][55];
void insert(char *s){//字典树建立无误
int len=strlen(s),u=0;
for(int i=0;i<len;i++)
{
int c=s[i]-'a';
if(ch[u][c]) u=ch[u][c];
else{
cnt++;
ch[u][c]=cnt;
u=ch[u][c];
}
//printf("%d ",u);
}
bo[u]++;//printf("%d;%d\n",u,bo[u]);
return;
}
void bfs(){
int q1=1,q2=0;
for(int i=0;i<26;i++){
if(ch[0][i])que[++q2]=ch[0][i];
}
for(q1,q2;q1<=q2;q1++){
int u=que[q1];
for(int i=0;i<26;i++)
{
int v=nxt[u];
if(ch[u][i]){
nxt[ch[u][i]]=ch[v][i];
que[++q2]=ch[u][i];
//printf("%d %d %d;",ch[u][i],nxt[ch[u][i]],q1);构建fail无误
}
else{
ch[u][i]=ch[v][i];
}
}
//printf("%d ",q2);
}
return;
}
void query(char *s)
{
int u=0,len=strlen(s);
for(int i=0;i<len;i++){
int c=s[i]-'a';
u=ch[u][c];
//printf("%d;",u);
for(int j=u;j;j=nxt[j]){
//printf(" %d ",j);
if(!val[j]&&bo[j]) ans+=bo[j],val[j]++;
}
}
return;
}
int main()
{
scanf("%d",&t);
while(t--){
cnt=0,ans=0;
memset(val,0,sizeof(val));
memset(ch,0,sizeof(ch));
memset(bo,0,sizeof(bo));
memset(que,0,sizeof(que));
memset(nxt,0,sizeof(nxt));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",stw[i]);
insert(stw[i]);
}
bfs();
scanf("%s",sta);
query(sta);
printf("%d\n",ans);
}
return 0;
}