http://acm.hdu.edu.cn/showproblem.php?pid=2222
今天学习了一下Aho-Corasick Automation。以前学了trie之后就停止搞字符串这方面了,因为今年NOI出现了AC自动机,所以要学习一下。
这个题目的代码很多,我只是贴出来纪念一下第一道AC自动机,我也是跟别人学的。希望做的题多了,我也可以形成自己的风格(这个风格就比较符合我了)……
加油!
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
using namespace std;
int n,Cases;
char pattern[51],match[1000001];
struct Aho_Corasick{
struct NODE{
int cnt;
NODE *fail,*next[26];
NODE(){fail=NULL,cnt=0;memset(next,0,sizeof(next));}
}*root,*p;
queue<NODE*> q;
void init(){root=new NODE();}
void build(){
q.push(root);
while(!q.empty()){
NODE *cur=q.front();q.pop();
for(int i=0;i<26;i++)
if(cur->next[i]){
for(p=cur->fail;p;p=p->fail)
if(p->next[i]){
cur->next[i]->fail=p->next[i];
break;
}
if(!p) cur->next[i]->fail=root;
q.push(cur->next[i]);
}
}
}
void insert(char *s){
int len=strlen(s);p=root;
for(int i=0;i<len;i++){
if(!p->next[s[i]-'a']) p->next[s[i]-'a']=new NODE();
p=p->next[s[i]-'a'];
}
p->cnt++;
}
void query(char *s){
int ans=0,len=strlen(s);p=root;
for(int i=0;i<len;i++){
while(!p->next[s[i]-'a'] && p!=root) p=p->fail;
p=p->next[s[i]-'a'];
if(!p) p=root;
for(NODE *j=p;j&&j->cnt!=-1;j=j->fail)
ans+=j->cnt,j->cnt=-1;
}
printf("%d\n",ans);
}
}AC;
int main(){
scanf("%d",&Cases);
while(Cases--){
scanf("%d",&n);
AC.init();
while(n--){
scanf("%s",pattern);
AC.insert(pattern);
}
AC.build();
scanf("%s",match);
AC.query(match);
}
return 0;
}