洛谷 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;
}

猜你喜欢

转载自www.cnblogs.com/lokiii/p/9013324.html