您的位置:首页 > 其它

【模板】AC自动机

2017-04-16 11:18 316 查看
我觉得AC自动机的难点和核心是构建失败指针,父亲的失败指针的儿子(son2)中有和儿子(son1)相同的,即为son1的失败指针





还是有个不懂的地方:第90行,跪求大佬赐教

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
using namespace std;
struct Tree{
int nxt[26];
int count;
int fail;
void init()
{
memset(nxt,-1,sizeof(nxt));
int fail=0;
int count=0;
}
}s[500009];
char str[100009],des[100009];
int n,sind=1,stu[500009];
void ins()//构建询问串trie树
{
int len=strlen(str);
int i,j,ind=0;
for(i=0;i<len;i++)
{
j=str[i]-'a';
if(s[ind].nxt[j]==-1)
{
s[sind].init();
s[ind].nxt[j]=sind;
sind++;
}
ind=s[ind].nxt[j];
}
s[ind].count++;//增加离根节点这条路径上字符串的个数,一条路上可能不止一个单词
}
void make_fail()
{
int qh=0,qt=0,ind,ind_f;
for(int i=0;i<26;i++)
{
if(s[0].nxt[i]!=-1)
stu[++qt]=s[0].nxt[i];//先把根下面链接的点入队
}
while(qh<qt)
{
ind=stu[++qh];
for(int i=0;i<26;i++)
{
if(s[ind].nxt[i]!=-1)//如果有 i ,求 i 的fail指针
{
stu[++qt]=s[ind].nxt[i];//入队
ind_f=s[ind].fail;//父亲的失败指针
int son=s[ind].nxt[i];

while(ind_f>0&&s[ind_f].nxt[i]==-1)
ind_f=s[ind_f].fail;//父亲失败指针的儿子中有相同的,即为son的失败指针

if(s[ind_f].nxt[i]!=-1)
ind_f=s[ind_f].nxt[i];

s[son].fail=ind_f;
}
}
}
}
int fd()
{
int cnt=0,i,j,len;
int ind=0;
len=strlen(des);
for(i=0;i<len;i++)
{
j=des[i]-'a';
while(ind>0&&s[ind].nxt[j]==-1)//一直在寻找合适的 fail 指针 ,如果是ind=0停止循环,直接判断
ind=s[ind].fail;

if(s[ind].nxt[j]!=-1)//如果找到了成功的fail,那么开始计数
{
ind=s[ind].nxt[j];
int p=ind;

while(p>0&&s[p].count!=-1)
{
cnt+=s[p].count;
s[p].count=-1;
p=s[p].fail;    //ind ? p ? 跳跳跳
}
}
}
return cnt;
}
int main()
{
s[0].init();//初始化根节点 !!!
scanf("%d\n",&n);
for(int i=1;i<=n;i++)
{
gets(str);
ins();
}
make_fail();

gets(des);
int ans=fd();

printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: