[Luogu3121][USACO15FEB]审查Censoring

题面

sol

开一个栈记录依次经过的\(AC\)自动机上的节点编号以及这一次的字母,若匹配到一个串就直接弹掉栈顶的\(len\)个元素,\(len\)为匹配到的模式串长度。弹栈顶直接\(top-=len\)即可。

code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 100005;
int n,len,l,tot,ch[26][N],fail[N],dep[N],top,S[2][N];
char s[N],c[N];
queue<int>Q;
void Insert()
{
    scanf("%s",c);l=strlen(c);
    int x=0;
    for (int i=0;i<l;i++)
    {
        if (!ch[c[i]-'a'][x]) ch[c[i]-'a'][x]=++tot;
        x=ch[c[i]-'a'][x];
    }
    dep[x]=l;
}
void Get_Fail()
{
    for (int i=0;i<26;i++) if (ch[i][0]) Q.push(ch[i][0]);
    while (!Q.empty())
    {
        int u=Q.front();Q.pop();
        for (int i=0;i<26;i++)
            if (ch[i][u]) fail[ch[i][u]]=ch[i][fail[u]],Q.push(ch[i][u]);
            else ch[i][u]=ch[i][fail[u]];
    }
}
int main()
{
    scanf("%s",s);len=strlen(s);
    scanf("%d",&n);
    for (int i=1;i<=n;i++) Insert();
    Get_Fail();
    for (int i=0,x=0;i<len;i++)
    {
        x=ch[s[i]-'a'][x];S[0][++top]=i;S[1][top]=x;
        if (dep[x]) top-=dep[x],x=S[1][top];
    }
    for (int i=1;i<=top;i++) printf("%c",s[S[0][i]]);
    return 0;
}
posted @ 2018-01-25 10:32  租酥雨  阅读(190)  评论(0编辑  收藏  举报