您的位置:首页 > 其它

Ac自动机_hdu_2222_Keywords Search

2016-08-01 10:55 501 查看
题目连接

这是一道AC自动机模板题,关于Ac自动机我总结一小点,因为对于字典树,它的难点就在于构建fail指针,要是fail指针会构建了Ac自动机也就基本上叫懂了。而相对于Kmp算法,AC自动机构建fail指针又有点不同,这里是站在父节点上构建子节点的fail指针,因为每次匹配都是站在父节点上找它是否存在某个子节点,因此当某个时刻某个节点不存在要找的下一个子节点时,就跳到它的fail指针处看那里是否可以匹配,因此当前节点fail指针指向的节点所表示的字符一定与当前节点相同,至于哪个是哪个前缀后缀什么的会了kmp的话就好理解了。。

语文好菜。。讲不下去了,上几个我学的时候用的链接吧,自己看看还是很好懂得。

KMP&AC自动机

AC自动机算法

代码君

#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <string>
#include <cstdio>
using namespace std;

struct node
{
int coun;
node *fail;
node *next[26];
node(){
coun=0;
fail=NULL;
memset(next,0,sizeof(next));
}
};

class Trie
{
private:
node *root;
public:
Trie(){
root=new node();
}
~Trie(){
del(root);
}
void del(node *p){
if(p==NULL)return;
for(int i=0;i<26;i++)del(p->next[i]);
delete p;
}
void insert(string s){
node *p=root;
int len=s.length();
for(int i=0;i<len;i++){
int id=s[i]-'a';
if(p->next[id]==NULL){
p->next[id]=new node();
}
p=p->next[id];
}
p->coun++;
}
void build(){
queue<node*>Q;
Q.push(root);
while(!Q.empty()){
node *p=Q.front();
Q.pop();
for(int i=0;i<26;i++){
if(p->next[i]!=NULL){
if(p==root)p->next[i]->fail=root;
else{
node *tmp=p->fail;
while(tmp!=root&&tmp->next[i]==NULL)tmp=tmp->fail;
tmp=tmp->next[i];
if(tmp==NULL)tmp=root;
p->next[i]->fail=tmp;
}
Q.push(p->next[i]);
}
}
}
}
int query(string s){
int ans=0;
node *p=root;
int len=s.length();
for(int i=0;i<len;i++){
int id=s[i]-'a';
while(p!=root && p->next[id]==NULL)p=p->fail;
p=p->next[id];
if(p==NULL)p=root;
node *tmp=p;
while(tmp!=root){
if(tmp->coun>=0){
ans+=tmp->coun;
tmp->coun=-1;
}else break;
tmp=tmp->fail;
}
}
return ans;
}
};

int main(){
int T;
cin>>T;
while(T--){
int n;
string s;
scanf("%d",&n);
Trie *ac=new Trie();
for(int i=0;i<n;i++){
cin>>s;
ac->insert(s);
}
cin>>s;
ac->build();
printf("%d\n",ac->query(s));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  kmp 字典树 AC自动机