洛谷 P3121 [USACO15FEB]審查(黃金)Censoring (Gold) 【AC自動機+棧】

這個和bzoj同名題不同,有多個匹配串
可是思路是同樣的,寫個AC自動機,一樣是開兩個棧,一個存字符,一個存當前點在trie樹上的位置,而後若是到了某個匹配串的末尾,則彈棧ios

#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;
}
相關文章
相關標籤/搜索