[BZOJ3940][Usaco2015 Feb]Censoring(AC自动机+栈)

来源:互联网 发布:nginx https 二级域名 编辑:程序博客网 时间:2024/06/06 00:38

题目描述

传送门

题解

和BZOJ3942是差不多的。
搞一个栈,然后边匹配边压栈,匹配不了就跳到失配,匹配成功就暴力弹栈。
需要注意的一点是,弹栈之后要将当前匹配的节点恢复到栈顶元素的位置,然后从下一个元素开始继续匹配。
单个串kmp就可以完成,多个串改成AC自动机来做。

代码

#include<iostream>#include<cstring>#include<cstdio>#include<queue>using namespace std;#define N 100005char s[N],t[N];int n,sz,len,top,lt[N],ch[N][30],fail[N],is_end[N],stack[N],loc[N];queue <int> q;void insert(int id){    int len=strlen(t),now=0;    for (int i=0;i<len;++i)    {        int x=t[i]-'a';        if (!ch[now][x]) ch[now][x]=++sz;        now=ch[now][x];    }    is_end[now]=id;}void make_fail(){    while (!q.empty()) q.pop();    for (int i=0;i<26;++i)        if (ch[0][i]) q.push(ch[0][i]);    while (!q.empty())    {        int now=q.front();q.pop();        for (int i=0;i<26;++i)        {            if (!ch[now][i])            {                ch[now][i]=ch[fail[now]][i];                continue;            }            fail[ch[now][i]]=ch[fail[now]][i];            q.push(ch[now][i]);        }    }}void ac(){    int now=0;    for (int i=0;i<len;++i)    {        stack[++top]=i;        int x=s[i]-'a';        int y=ch[now][x];        if (y&&is_end[y])        {            int tmp=lt[is_end[y]];            top-=tmp;            now=loc[stack[top]];            continue;        }        loc[i]=now=y;    }}int main(){    gets(s);len=strlen(s);    scanf("%d\n",&n);    for (int i=1;i<=n;++i)    {        gets(t);lt[i]=strlen(t);        insert(i);    }    make_fail();    ac();    for (int i=1;i<=top;++i)        putchar(s[stack[i]]);    putchar('\n');}
0 0