搜索关键词
给定 n 个长度不超过 50 的由小写英文字母组成的单词,以及一篇长为 m 的文章。
请问,有多少个单词在文章中出现了。
输入格式
第一行包含整数 T,表示共有 T 组测试数据。
对于每组数据,第一行一个整数 n,接下去 n 行表示 n 个单词,最后一行输入一个字符串,表示文章。
输出格式
对于每组数据,输出一个占一行的整数,表示有多少个单词在文章中出现。
数据范围
,
输入样例:
1
5
she
he
say
shr
her
yasherhs
输出样例:
3
题解:
第一道ac自动机的题,相对于kmp,ac自动机就是把一维的信息放在了树上来进行统计了。
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+7,S=55,M=1e6+7;
int ne[N*S],con[N*S],tr[N*S][26],cnt;
char str[M];
queue<int> q;
void insert()
{
int p=0;
for(int i=0;str[i];i++){
int t=str[i]-'a';
if(!tr[p][t]) tr[p][t]=++cnt;
p=tr[p][t];
}
con[p]++;
}
void build()
{
for(int i=0;i<26;i++){
if(tr[0][i]) q.push(tr[0][i]);
}
while (!q.empty()){
int t=q.front(); q.pop();
for(int i=0;i<26;i++){
int p=tr[t][i];
if(!p) tr[t][i]=tr[ne[t]][i];//没路建路
else{
ne[p]=tr[ne[t]][i];//有路,下次没有匹配到就可以跳回这里
q.push(p);//当前层节点放入
}
}
}
}
int main()
{
int t; scanf("%d",&t);
while(t--){
cnt=0;
memset(tr,0,sizeof tr);
memset(con,0,sizeof con);
memset(ne,0,sizeof ne);
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%s",str);
insert();
}
scanf("%s",str);
build();
int res=0;
for(int i=0,j=0;str[i];i++){
int t=str[i]-'a';
j=tr[j][t];
int p=j;
while(p){
res+=con[p];
con[p]=0;
p=ne[p];
}
}
cout<<res<<endl;
}
return 0;
}
来源:CSDN
作者:行走天涯的豆沙包
链接:https://blog.csdn.net/weixin_42979819/article/details/104224887