CENSORING——AC 自动机
Posted chmwt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CENSORING——AC 自动机相关的知识,希望对你有一定的参考价值。
题目
【题目描述】
FJ 为它的奶牛订阅了很多杂志,balabala.......,其中有一些奶牛不宜的东西 (比如如何煮牛排)。
FJ 将杂志中所有的文章提取出来组成一个长度最多为 $ 10^5 $ 的字符串 S。他有一个要从 S 中删除的词语的列表,$ t_1,t_2...t_n $。
FJ 每次找到最早的出现在列表里的子串,然后将其删去。他重复此过程,直到找不到这样的子串。值得注意的是删除一个单词可能产生一个新的之前并没有出现过的要被删除的单词。
FJ 保证列表中没有一个字符串是另一个字符串的子串。要就是说每次要删的单词是唯一确定的。
帮助 FJ 确定最终 S 的删减版。
【输入格式】
第一行 S,第二行 $N$,接下来 $n$ 行 $t_1,t_2,...t_n$。所有字符串只包含小写字母,所有字符串的总长不超过 $10^5$。
【输出格式】
S 的删减版。保证结果不为空
【样例输入】
begintheescapexecutionatthebreakofdawn
2
escape
execution
【样例输出】
beginthatthebreakofdawn
题解
对于 T 建 AC 自动机,然后将 $ S $ 逐位压入栈中,跑 AC 自动机,当当前节点为 $ T_i $ 的结尾时,弹出即可
代码
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define _(d) while(d(isdigit(ch=getchar()))) 4 using namespace std; 5 int R(){ 6 int x;bool f=1;char ch;_(!)if(ch==‘-‘)f=0;x=ch^48; 7 _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;} 8 const int N=1e5+5; 9 int n,cnt,fa[N],pre[N],top,num[N],las[N],sta[N],tr[N][28],fail[N]; 10 char str[N],ch[N]; 11 void insert(int k){ 12 int len=strlen(ch+1),x=0; 13 for(int i=1;i<=len;i++){ 14 if(!tr[x][ch[i]-‘a‘])tr[x][ch[i]-‘a‘]=++cnt,fa[cnt]=x; 15 x=tr[x][ch[i]-‘a‘]; 16 } 17 num[k]=len,pre[x]=k; 18 } 19 void build(){ 20 queue<int>q; 21 for(int i=0;i<26;i++) 22 if(tr[0][i])q.push(tr[0][i]); 23 while(!q.empty()){ 24 int x=q.front();q.pop(); 25 for(int i=0;i<26;i++) 26 if(tr[x][i]) 27 fail[tr[x][i]]=tr[fail[x]][i],q.push(tr[x][i]); 28 else tr[x][i]=tr[fail[x]][i]; 29 } 30 } 31 int main(){ 32 scanf("%s",str+1); 33 int len=strlen(str+1);n=R(); 34 for(int i=1;i<=n;i++) 35 scanf("%s",ch+1),insert(i); 36 build(); 37 for(int i=1,x=0;i<=len;i++){ 38 sta[++top]=i; 39 int p=str[i]-‘a‘,y=tr[x][p]; 40 if(y&&pre[y]) 41 top-=num[pre[y]],x=las[sta[top]]; 42 else las[i]=x=y; 43 } 44 for(int i=1;i<=top;i++) 45 putchar(str[sta[i]]); 46 return puts(""),0; 47 }
以上是关于CENSORING——AC 自动机的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 3940: [Usaco2015 Feb]Censoring -- AC自动机
bzoj3940[Usaco2015 Feb]Censoring*