AC自动机
要求对一个文本统计出现过的模板个数
理解了AC自动机的算法就很容易了
指针版
#include<queue>
#include<stdio.h>
#include<iostream>
#include<cstdio>
using namespace std;
struct node{
int fl;
node *next[26],*fail;
node(){
memset(next,0,sizeof next);
fail=NULL;
fl=0;
}
};
char s[1000050],ss[1005];
void ins(node *rt,char mb[]){
int i=0,x;
node *tmp=rt;
while(mb[i]){
x=mb[i]-'a';
if(tmp->next[x]==NULL)tmp->next[x]=new node();
tmp=tmp->next[x];
i++;
}
tmp->fl++;
}
queue<node *>q;
void build(node *rt){
node *tmp;
q.push(rt);
while(!q.empty()){
tmp=q.front();
q.pop();
for(int i=0;i<26;++i)
if(tmp->next[i]){
q.push(tmp->next[i]);
node *p=tmp->fail;
while(p){
if(p->next[i]){
tmp->next[i]->fail=p->next[i];
break;
}
p=p->fail;
}
if(!p)tmp->next[i]->fail=rt;
}
}
}
int query(node *rt){
int i=0,cnt=0,x;
node *tmp=rt;
while(s[i]){
x=s[i]-'a';
while(!tmp->next[x]&&tmp!=rt)tmp=tmp->fail;
tmp=tmp->next[x];
if(!tmp)tmp=rt;
node *p=tmp;
while(p&&p->fl!=-1){
cnt+=p->fl;
p->fl=-1;
p=p->fail;
}
i++;
}
return cnt;
}
int main(){
int n;
int t;scanf("%d",&t);
while(t--){
scanf("%d",&n);
node *root=new node();
for(int i=0;i<n;++i){
scanf("%s",ss);
ins(root,ss);
}
build(root);
scanf("%s",s);
printf("%d\n",query(root));
}
return 0;
}
数组版:(注意C++会TLE 可能与内存分配有关)
#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<queue>
using namespace std;
#define M 510000
#define size 26
struct node{
int ch[M][26],fail[M],end[M],cnt,root;
int add(){
++cnt; memset(ch[cnt],-1,sizeof ch[cnt]);
end[cnt]=0;
return cnt;
}
void init(){
cnt=0;root=add();
}
void ins(char s[]){
int len=(int)strlen(s);int p=root;
for(int i=0;i<len;++i){
int x=s[i]-'a';
if(ch[p][x]==-1)ch[p][x]=add();
p=ch[p][x];
}
end[p]++;
}
queue<int>q;
void build(){
int p=root;fail[root]=root;
for(int i=0;i<size;++i){
if(ch[p][i]==-1) ch[p][i]=p;
else { q.push(ch[p][i]); fail[ch[p][i]]=p;}
}
while(!q.empty()){
p=q.front();q.pop();
for(int i=0;i<size;++i){
if(ch[p][i]==-1) ch[p][i]=ch[fail[p]][i];
else{fail[ch[p][i]]=ch[fail[p]][i]; q.push(ch[p][i]);}
}
}
}
void query(char s[]){
int len=(int)strlen(s),pos=root,ans=0;
for(int i=0;i<len;++i){
int x=s[i]-'a';
int tmp=ch[pos][x]; pos=tmp;
while(tmp!=root){
ans+=end[tmp];end[tmp]=0;tmp=fail[tmp];
}
}
printf("%d\n",ans);
}
}x;
char s1[1005],s2[1100000];
int main(){
int t,n;scanf("%d",&t);
while(t--){
scanf("%d",&n);x.init();
for(int i=0;i<n;++i){
scanf("%s",s1);
x.ins(s1);
}
x.build();
scanf("%s",s2);
x.query(s2);
}
return 0;
}