1. 程式人生 > >3940. [USACO15FEB]Censoring【AC自動機+棧】

3940. [USACO15FEB]Censoring【AC自動機+棧】

art push rem sed delete rop max coo ria

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 }

3940. [USACO15FEB]Censoring【AC自動機+棧】