3940. [USACO15FEB]Censoring【AC自动机+栈】

Description

Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they have plenty

of material to read while waiting around in the barn during milking sessions. Unfortunately, the latest

issue contains a rather inappropriate article on how to cook the perfect steak, which FJ would rather his

cows not see (clearly, the magazine is in need of better editorial oversight).

FJ has taken all of the text from the magazine to create the string S of length at most 10^5 characters.

He has a list of censored words t_1 ... t_N that he wishes to delete from S. To do so Farmer John finds

the earliest occurrence of a censored word in S (having the earliest start index) and removes that instance

of the word from S. He then repeats the process again, deleting the earliest occurrence of a censored word

from S, repeating until there are no more occurrences of censored words in S. Note that the deletion of one

censored word might create a new occurrence of a censored word that didn‘t exist before.

Farmer John notes that the censored words have the property that no censored word appears as a substring of

another censored word. In particular this means the censored word with earliest index in S is uniquely

defined.Please help FJ determine the final contents of S after censoring is complete.

FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S。他有一个包含n个单词的列表,列表里的n个单词

记为t_1...t_N。他希望从S中删除这些单词。

FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中

没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词

FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的

请帮助FJ完成这些操作并输出最后的S

Input

The first line will contain S. The second line will contain N, the number of censored words. The next N lines contain the strings t_1 ... t_N. Each string will contain lower-case alphabet characters (in the range a..z), and the combined lengths of all these strings will be at most 10^5.

第一行包含一个字符串S

第二行包含一个整数N

接下来的N行,每行包含一个字符串,第i行的字符串是t_i

Output

The string S after all deletions are complete. It is guaranteed that S will not become empty during the deletion process.

一行,输出操作后的S

Sample Input

begintheescapexecutionatthebreakofdawn
2
escape
execution

Sample Output

beginthatthebreakofdawn

一开始的确没啥思路……一看到有栈这个标签就明了了……
果然我还是水平太菜啊
不过一看到栈这个题就没什么思考难度了……就基本全靠细节了
首先把自动机建出来……话说我这几天才发现原来自己建的一直叫trie图
然后一位一位放到自动机上跑。
分两种情况:
1、栈空
   判断是否是根节点的一个儿子即可(即判断是否是单词的第一位)
2、栈不为空
   判断当前位能否和上一位匹配,如果不能的话就清空栈(因为有这一位挡着就已经前功尽弃了)
然后当当前位匹配到某一位的末尾后,就将这个单词从栈中清空(因为题目说了越靠前出现的越早清空)
清空栈的时候输出一下就好了(除了匹配到的单词不输出)

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<queue>
 5 #define N (100000+10)
 6 using namespace std;
 7 int Fail[N],Son[N][27],End[N];
 8 int n,sz,maxn,stack[N],top;
 9 char s[N],st[N],ch[N];
10 queue<int>q;
11
12 void Insert(char s[])
13 {
14     int len=strlen(s),now=0;
15     for (int i=0;i<len;++i)
16     {
17         int x=s[i]-‘a‘;
18         if (!Son[now][x]) Son[now][x]=++sz;
19         now=Son[now][x];
20         ch[now]=s[i];
21     }
22     End[now]=len;
23 }
24
25 void Build_Fail()
26 {
27     for (int i=0;i<26;++i)
28         if (Son[0][i])
29             q.push(Son[0][i]);
30     while (!q.empty())
31     {
32         int now=q.front(); q.pop();
33         for (int i=0;i<26;++i)
34         {
35             if (!Son[now][i])
36             {
37                 Son[now][i]=Son[Fail[now]][i];
38                 continue;
39             }
40             Fail[Son[now][i]]=Son[Fail[now]][i];
41             q.push(Son[now][i]);
42         }
43     }
44 }
45
46 void Compare(char s[])
47 {
48     int len=strlen(s);
49     for (int i=0;i<len;++i)
50     {
51         int x=s[i]-‘a‘;
52         if (!top)
53         {
54             if (Son[0][x])
55                 stack[++top]=Son[0][x];
56             else
57                 printf("%c",s[i]);
58         }
59         else
60         {
61             int son=Son[stack[top]][x];
62             if (Son[stack[top]][x])
63                 stack[++top]=son;
64             else
65             {
66                 for (int j=1;j<=top;++j)
67                     printf("%c",ch[stack[j]]);
68                 printf("%c",s[i]);
69                 top=0;
70             }
71         }
72         if (End[stack[top]])
73         {
74             int t=End[stack[top]];
75             for (int i=1;i<=t;++i)
76                 top--;
77         }
78     }
79     for (int i=1;i<=top;++i)
80         printf("%c",ch[stack[i]]);
81 }
82
83 int main()
84 {
85     scanf("%s%d",s,&n);
86     for (int i=1;i<=n;++i)
87         scanf("%s",st),Insert(st);
88     Build_Fail();
89     Compare(s);
90 }

原文地址:https://www.cnblogs.com/refun/p/8685682.html

时间: 2024-10-09 05:43:35

3940. [USACO15FEB]Censoring【AC自动机+栈】的相关文章

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

CENSORING——AC 自动机

题目 [题目描述] FJ 为它的奶牛订阅了很多杂志,balabala.......,其中有一些奶牛不宜的东西 (比如如何煮牛排). FJ 将杂志中所有的文章提取出来组成一个长度最多为 $ 10^5 $ 的字符串 S.他有一个要从 S 中删除的词语的列表,$ t_1,t_2...t_n $. FJ 每次找到最早的出现在列表里的子串,然后将其删去.他重复此过程,直到找不到这样的子串.值得注意的是删除一个单词可能产生一个新的之前并没有出现过的要被删除的单词. FJ 保证列表中没有一个字符串是另一个字符

【BZOJ3940】【Usaco2015 Feb】Censoring AC自动机

链接: #include <stdio.h> int main() { puts("转载请注明出处[vmurder]谢谢"); puts("网址:blog.csdn.net/vmurder/article/details/44960463"); } 题意: 题意同BZOJ3942,不过要删除的串是多串 http://blog.csdn.net/vmurder/article/details/44959895 题解: --思路一模一样,除了不用kmp用AC

bzoj 3940: [Usaco2015 Feb]Censoring -- AC自动机

3940: [Usaco2015 Feb]Censoring Time Limit: 10 Sec  Memory Limit: 128 MB Description Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they have plenty of material to read while waiting around in the barn during

bzoj3940 censoring 题解(AC自动机)

题目描述 Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they have plenty of material to read while waiting around in the barn during milking sessions. Unfortunately, the latest issue contains a rather inappropria

【AC自动机】Censoring

[题目链接] https://loj.ac/problem/10059 [题意] 有一个长度不超过  1e5 的字符串 .Farmer John 希望在 T 中删掉 n 个屏蔽词(一个屏蔽词可能出现多次),这些词记为 P1,P2……Pn. [题解] 利用栈来进行匹配删除即可. 1.建模式串的AC自动机.(结尾位置记录长度) 2.利用文本串跑一遍AC自动机. 3.在跑的过程中,如果遇到屏蔽字的结尾时,相应操作为:1.把栈里弹出模式串的长度,2.同时文本串继续跑. 4.跑的过程中还需要一个辅助的数组

AC自动机总结

AC自动机总结 自动机的概念: 自动机又称有限状态机,是从初始状态不断接受输入,根据输入数据和当前状态跳转到下一状态的一种机器. AC自动机可以实现多串匹配单串.复杂度是\(O(n+m)\),也就是匹配串长+模式串总长. AC自动机匹配失配时,类似KMP算法的next数组,AC自动机上有fail指针可以跳到下一个应该进行匹配的状态. fail指针的一般定义是:沿着父亲的fail指针一直向上跳,直到跳到某一个节点,这个节点拥有与自己相同字母的子节点,那么fail指针就指向这个相同字母的子节点. 一

AC自动机学习小结

AC自动机 简要说明 \(AC\) 自动机,全称 \(Aho-Corasick\ automaton\) ,是一种有限状态自动机,应用于多模式串匹配.在 \(OI\) 中通常搭配 \(dp\) 食用.因为它是状态自动机. 感性理解:在 \(Trie\) 树上加上 \(fail\) 指针.具体的讲解可以去看dalao们的博客(因为我实在是太菜了讲不好). 题目 Keywords Search 题目:给若干个模式串,再给一个文本串,问有几个模式串在文本串中出现过. 板子题.注意一个模式串只被计算一次

LA_3942 LA_4670 从字典树到AC自动机

首先看第一题,一道DP+字典树的题目,具体中文题意和题解见训练指南209页. 初看这题模型还很难想,看过蓝书提示之后发现,这实际上是一个标准DP题目:通过数组来储存后缀节点的出现次数.也就是用一颗字典树从后往前搜一发.最开始觉得这种搞法怕不是要炸时间,当时算成了O(N*N)毕竟1e5的数据不搞直接上N*N的大暴力...后来发现,字典树根本跑不完N因为题目限制字典树最多右100层左右. 实际上这道题旧思想和模型来说很好(因为直观地想半天还真想不出来..)但是实际实现起来很简单--撸一发字典树就好了