洛谷 P3121 [USACO15FEB]审查(黄金)Censoring (Gold) 【AC自动机+栈】

这个和bzoj同名题不一样,有多个匹配串
但是思路是一样的,写个AC自动机,同样是开两个栈,一个存字符,一个存当前点在trie树上的位置,然后如果到了某个匹配串的末尾,则弹栈

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int N=100005;
int n,t[N],top;
char a[N],b[N],s[N];
struct AC
{
	int tot,c[N][27],f[N],l[N];
	void ins(char s[])
	{
		int len=strlen(s),nw=0;
		for(int i=0;i<len;i++)
		{
			if(!c[nw][s[i]-'a'])
				c[nw][s[i]-'a']=++tot;
			nw=c[nw][s[i]-'a'];
		}
		l[nw]=len;
	}
	void build()
	{
		queue<int>q;
		for(int i=0;i<26;i++)
			if(c[0][i])//!!!!!!!!!!!!!!!!!!!!!!!!!!!
				f[c[0][i]]=0,q.push(c[0][i]);
		while(!q.empty())
		{
			int u=q.front();
			q.pop();
			for(int i=0;i<26;i++)
			{
				if(c[u][i])
					f[c[u][i]]=c[f[u]][i],q.push(c[u][i]);
				else
					c[u][i]=c[f[u]][i];
			}
		}
	}
	void wk(char a[])
	{
		int len=strlen(a),nw=0;
		for(int i=0;i<len;i++)
		{
			nw=c[nw][a[i]-'a'];
			s[++top]=a[i],t[top]=nw;
			if(l[nw])
				top-=l[nw],nw=t[top];
		}
		for(int i=1;i<=top;i++)
			putchar(s[i]);
	}
}ac;
int main()
{
	scanf("%s%d",a,&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%s",b);
		ac.ins(b);
	}
	ac.build();
	ac.wk(a);
	return 0;
}
原文地址:https://www.cnblogs.com/lokiii/p/9013324.html