bzoj 3172: [Tjoi2013]单词【AC自动机】

一眼AC自动机,就是先把串建一个自动机,标记每个串在自动机上的位置,然后加上间隔符连成一个串在自动机上跑,每跑到一个点就说明这个串以及它到root的所有点表示的串都要被更新一次
先在点上打上标记,最后dfs fail数向上传递
并不是到结尾点才能更新……脑子抽了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=1000005;
int n,ch[N][27],fa[N],id[N],a[N],tot=1,con,h[N],cnt;
char s[N<<1],c[N];
struct qwe
{
	int ne,to;
}e[N<<1];
void add(int u,int v)
{
	cnt++;
	e[cnt].ne=h[u];
	e[cnt].to=v;
	h[u]=cnt;
}
void dfs(int u)
{
	for(int i=h[u];i;i=e[i].ne)
	{
		dfs(e[i].to);
		a[u]+=a[e[i].to];
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",c+1);
		int nw=1;
		for(int j=1,len=strlen(c+1);j<=len;j++)
		{
			s[++con]=c[j]-'a';
			if(!ch[nw][c[j]-'a'])
				ch[nw][c[j]-'a']=++tot;
			nw=ch[nw][c[j]-'a'];
		}
		id[i]=nw;
		s[++con]=26;
	}
	queue<int>q;
	for(int i=0;i<=26;i++)
	{
		if(ch[1][i])
			q.push(ch[1][i]),fa[ch[1][i]]=1;
		else
			ch[1][i]=1;
	}
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=0;i<=26;i++)
		{
			if(ch[u][i])
				fa[ch[u][i]]=ch[fa[u]][i],q.push(ch[u][i]);
			else
				ch[u][i]=ch[fa[u]][i];
		}
	}
	for(int i=2;i<=tot;i++)
		add(fa[i],i);
	int nw=1;
	for(int i=1;i<=con;i++)
	{
		nw=ch[nw][s[i]];
		a[nw]++;
	}
	dfs(1);
	for(int i=1;i<=n;i++)
		printf("%d\n",a[id[i]]);
	return 0;
}
posted @ 2019-02-25 22:01  lokiii  阅读(109)  评论(0编辑  收藏  举报