您的位置:首页 > 其它

文章标题 HDU 2222 : Keywords Search (AC自动机模板)

2017-08-25 17:21 627 查看
题目链接

题意:有n个单词,然后有一个文本串,问有多少个单词出现在文本串中出现,每个单词只技术一次

分析:ac自动机模板题,得注意单词只计数一次。

代码:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <queue>
using namespace std;
const int maxn=500000+10;
int n;
int ch[maxn][26];//trie中每个点的儿子节点编号
int fail[maxn];
int last[maxn];//后缀链接:沿着i的失配指针走遇到的下一个单词节点的编号
int val[maxn];//点上的标记(比如标记是否是单词节点)
int sz;
int root;
int newnode (){//新节点
memset (ch[sz],0,sizeof (ch[sz]));//将其孩子置为0
val[sz]=0;
return sz++;
}
void init(){//初始化
sz=0;
root=newnode();
}
int insert(char *str){//建树
int len=strlen(str);
int now=root;
for (int i=0;i<len;i++){
int c=str[i]-'a';
if (!ch[now][c]){
memset (ch[sz],0,sizeof (ch[sz]));
val[sz] = 0;
ch[now][c] = sz++;
}
now=ch[now][c];
}
val[now]++;
return now;
}
void getfail(){
queue<int>q;
fail[root]=root;
for (int i=0;i<26;i++){
int u=ch[root][i];
if (u){
fail[u]=0;
last[u]=0;
q.push(u);
}
}
while (!q.empty()){
int now=q.front();q.pop();
for (int i=0;i<26;i++){
int u=ch[now][i];
//u=ch[now][i]就是我们说的当前节点A,now是A的父节点,
//那么fail[now]就相当于我们说的父节点的失败节点C
if (!u){
/*
如果当前节点now没有i这个儿子u,
直接让这个点的第i个儿子u指向now的失败节点的第i个儿子。
因为如果一个串在AC自动机里面走,走到now时要走的下一个节点是i,
now又没有i这个儿子,因此一定会是失配的。
既然失配了,now就要沿着fail指针走,试图去匹配失败节点的第i个儿子。
这里的ch[now][i]=ch[fail[now]][i]就相当于
让他直接去匹配now的失败节点的第i个儿子
*/
ch[now][i]=ch[fail[now]][i];
}
else {
//如果当前节点now有i这个儿子u,
//那么u的失败节点显然要指向C(即fail[now])的第i个儿子
fail[u]=ch[fail[now]][i];
last[u]=val[fail[u]]?fail[u]:last[fail[u]];
q.push(u);
}
}
}
}
int quary(char *str){
int len=strlen(str);
int now=root;
int ans=0;
for (int i=0;i<len;i++){
now=ch[now][str[i]-'a'];
int tmp=now;
if (tmp!=root&&!val[tmp]&&last[tmp]){
tmp=last[tmp];
}
while (tmp!=root&&val[tmp]){
ans+=val[tmp];
val[tmp]=0;
tmp=last[tmp];
}
}
return ans;
}
char text[1000005];
char str[55];
int main()
{
int t;
scanf("%d",&t);
while (t--){
init();
scanf ("%d",&n);
for (int i=0;i<n;i++){
scanf ("%s",str);
insert (str);
}
getfail();
scanf ("%s",text);
printf ("%d\n",quary(text));
}
return 0;
}
/*
100
2
c
abcd
abcde
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: