您的位置:首页 > 其它

Keywords Search(hdu 2222)

2017-01-04 09:55 513 查看
题意:给出n个单词,一篇文章,询问有几个单词在文章中出现过。

/*
AC自动机的裸题。
题目标号牛的一比。
*/
#include<cstdio>
#include<cstring>
#include<iostream>
#define N 500010
#define M 1000010
using namespace std;
int a
[26],danger
,point
,mark
,q
,n,size;
char ch[M];
void insert(){
int len=strlen(ch),now=1;
for(int i=0;i<len;i++){
int t=ch[i]-'a';
if(!a[now][t])a[now][t]=++size;
now=a[now][t];
}
danger[now]++;
}
void acmach(){//构建自动机
int h=0,t=1;
q[1]=1;point[1]=0;
while(h<t){
int now=q[++h];
for(int i=0;i<=25;i++){
if(!a[now][i])continue;
int k=point[now];
while(!a[k][i])k=point[k];
point[a[now][i]]=a[k][i];//类似于kmp的失败数组
q[++t]=a[now][i];
}
}
}
void solve(){
int len=strlen(ch),k=1,ans=0;
for(int i=0;i<len;i++){
mark[k]=1;
int t=ch[i]-'a';
while(!a[k][t])k=point[k];
k=a[k][t];
if(mark[k])continue;
for(int j=k;j;j=point[j]){
ans+=danger[j];
danger[j]=0;//每个单词只记录一次
}
}
printf("%d\n",ans);
}
int main(){
int T;scanf("%d",&T);
while(T--){
memset(a,0,sizeof(a));
memset(point,0,sizeof(point));
memset(danger,0,sizeof(danger));
memset(mark,0,sizeof(mark));
size=1;
for(int i=0;i<=25;i++)a[0][i]=1;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",ch);
insert();
}
acmach();
scanf("%s",ch);
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: