现在来讲,我对AC自动机的理解,就是说,建一棵TRIE树,然后利用BFS遵循每次找到到根的路径上的一个节点,该节点的儿子中有该字符,就把fail指针赋给它。读入就是建trie树,query比较烦,还需理解。明天的目标是彻底搞懂AC自动机,然后复习一下splay和树链剖分,然后A两道题库题后,巩固AC自动机
#include<cstdio>
#include<queue>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int t,n;
char st[100001];
struct AK_automic_machine{
int en[1000001],son[1000001][26],fail[1000001],end[1000001],root,S;
int newnode()
{
S++;
for(int i=0;i<=25;i++) son[S][i]=-1;
end[S]=0;
return S;
}
void clear()
{
S=0;
root=newnode();
}
void add(char *s)
{
int len=strlen(s);
int p=root;
for(int i=0;i<len;i++)
{
if(son[p][s[i]-'a']==-1)
{
son[p][s[i]-'a']=newnode();
}
p=son[p][s[i]-'a'];
}
end[p]++;
}
void build()
{
queue<int>q;
fail[root]=root;
for(int i=0;i<=25;i++)
if(son[root][i]!=-1)
{
fail[son[root][i]]=root;q.push(son[root][i]);
}
else son[root][i]=root;
while(!q.empty())
{
int node=q.front();q.pop();
for(int i=0;i<=25;i++)
{
if(son[node][i]==-1)
{
son[node][i]=son[fail[node]][i];
}
else
{
fail[son[node][i]]=son[fail[node]][i];
q.push(son[node][i]);
}
}
}
}
int query(char *s)
{
int len=strlen(s);
int ans=0;
int p=root;
int tmp;
for(int i=0;i<len;++i)
{
p=son[p][s[i]-'a'];
tmp=p;
while(tmp!=root)
{
ans+=end[tmp];
end[tmp]=0;
tmp=fail[tmp];
}
}
return ans;
}
}AC;
int main()
{
scanf("%d",&t);
while(t--)
{
AC.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%s",st);AC.add(st);
}
scanf("%s",st);
AC.build();
printf("%d",AC.query(st));
}
}
HDU2222冥冥懂了AC自动机的原理,代码能力太弱,写不出来,明天继续研究!
#include<cstdio>
#include<queue>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
int t,n;
char st[1001001];
struct AK_automic_machine{
int son[501001][28],fail[501001],end[501001],root,S;
int newnode()
{
S++;
for(int i=0;i<26;i++) son[S][i]=-1;
end[S]=0;
return S;
}
void clear()
{
S=0;
root=newnode();
}
void add(char *s)
{
int i,len=strlen(s);
int p=root;
for(i=0;i<len;i++)
{
if(son[p][s[i]-'a']==-1)
{
son[p][s[i]-'a']=newnode();
}
p=son[p][s[i]-'a'];
}
end[p]++;
}
void build()
{
fail[root]=root;
queue<int>q;
for(int i=0;i<26;i++)
if(son[root][i]==-1) son[root][i]=root;
else{fail[son[root][i]]=root;q.push(son[root][i]);}
while(!q.empty())
{
int node=q.front();q.pop();
for(int i=0;i<=25;i++)
{
if(son[node][i]==-1)
{
son[node][i]=son[fail[node]][i];
}
else
{
fail[son[node][i]]=son[fail[node]][i];
q.push(son[node][i]);
}
}
}
}
int query(char *s)
{
int len=strlen(s);
int ans=0;
int p=root;
for(int i=0;i<len;++i)
{
p=son[p][s[i]-'a'];
int tmp=p;
while(tmp!=root)
{
ans+=end[tmp];
end[tmp]=0;tmp=fail[tmp];
}
}
return ans;
}
}AC;
int main()
{
scanf("%d",&t);
while(t--)
{
AC.clear();
scanf("%d",&n);
while(n--)
{
scanf("%s",st);
AC.add(st);
}
AC.build();
scanf("%s",st);
printf("%d\n",AC.query(st));
}
return 0;
}