AC自动机中fail指针

过程

fail指针可以说是AC自动机里最难理解的东西,怎样更好的理解AC自动机的fail指针?
先来看一幅图:

看这幅图上的fail指针是怎么构造的.

树上的词分别是:

{he,hers,his,she}

按图所示分成3层。看到第三层,是"she",其中:
下面以"she"创建fail指针的过程为例

  • s指向root

  • h先找到s的fail指针

发现是0号指针,不是h,然后h就不高兴了,再问问s的fail指针root:“你有没有儿子和我同名叫h的”
root说:“有,你指向他吧”,然后h就高兴的指向了第一行的h.

  • e开始找了

首先问他老爸h:“你的fail指针指着谁”
h说:“图上第一行那个h啊”
然后e就屁颠屁颠地跑去问图上第一行那个h:“你有没有名字和我一样的儿子啊”
图上第一行那个h说:“有,他地址是xxx”
最后e的fail指针就指向xxx地址,也就是第一行那个e了

  • 作用

发现这样,如果一个字符串查到第三行的e以后的字符才不匹配,那说明他前面应该有个‘he’
刚好e的失败指针指向的是第一行的‘he...’的那个e;
这样就不用从h开始再找一遍,而是接着第一行的e继续往后找,从而节省了时间.

转自:AC自动机 - 关于Fail指针

\(code\)

void get_fail()
{
	queue<int>q;
	for(int i=0;i<26;++i){//提前处理第二层的fail指针 
		if(ac[0].vis[i]!=0)
		{
			ac[ac[0].vis[i]].fail=0;//指向根节点
			q.push(ac[0].vis[i]); 
		}
	} 
	while(!q.empty())//bfs求fail指针 
        {
		int u=q.front();
		q.pop();
		for(int i=0;i<26;++i)
		{
			if(ac[u].vis[i])//存在这个节点 
			{
				ac[ac[u].vis[i]].fail=ac[ac[u].fail].vis[i];
				//子节点的fail指针指向当前节点的
                                //fail指针所指向的节点的相同子节点 
                                q.push(ac[u].vis[i]); 
		        }
		        else 
                            ac[u].vis[i]=ac[ac[u].fail].vis[i]; 
			//当前节点的这个子节点指向当
                        //前节点fail指针的这个子节点 
		}
	}
}
posted @ 2020-03-14 17:31  pyyyyyy  阅读(712)  评论(4编辑  收藏  举报