1. 程式人生 > >「USACO15FEB」「LuoguP3121」審查(黃金)Censoring (Gold)(AC自動機

「USACO15FEB」「LuoguP3121」審查(黃金)Censoring (Gold)(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 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

輸入輸出格式

輸入格式:

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.

輸出格式:

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

輸入輸出樣例

輸入樣例#1: 複製
begintheescapexecutionatthebreakofdawn 
2 
escape 
execution 
輸出樣例#1: 複製
beginthatthebreakofdawn 

題解

首先把單詞建個Trie圖,get_fail,然後用文字串跑AC自動姬。

再開兩個棧,一個存經過的Trie上的點,一個存點代表的文字串。

如果跑到了某個單詞的結尾,就把棧彈到這個單詞的開頭,並且把當前所在點修改為點棧的點。

最後輸出文字棧的字元就行了。

 1 /*
 2     qwerta
 3     P3121 [USACO15FEB]審查(黃金)Censoring (Gold)
 4     Accepted
 5     100
 6     程式碼 C++,1.34KB
 7     提交時間 2018-10-20 21:57:54
 8     耗時/記憶體
 9     245ms, 12716KB
10 */
11 #include<iostream>
12 #include<cstring>
13 #include<cstdio>
14 #include<queue>
15 using namespace std;
16 string s;//文字串
17 string t;//單詞
18 struct emm{
19     int nxt[26];
20     int fal,d,tag;
21 }a[3000003];//AC姬
22 queue<int>q;
23 int st[100003];//點編號棧
24 char ans[100003];//點代表的字元棧
25 int main()
26 {
27     //freopen("a.in","r",stdin);
28     ios::sync_with_stdio(false);
29     cin>>s;
30     int n;
31     cin>>n;
32     int cnt=0;
33     //Trie
34     for(int i=1;i<=n;++i)
35     {
36         cin>>t;
37         int lent=t.length(),k=0;
38         for(int j=0;j<lent;++j)
39         {
40             if(!a[k].nxt[t[j]-'a'])
41               a[k].nxt[t[j]-'a']=++cnt;
42             k=a[k].nxt[t[j]-'a'];
43             a[k].d=j+1;
44         }
45         a[k].tag++;
46     }
47     //get_fail
48     for(int i=0;i<26;++i)
49     if(a[0].nxt[i])
50       q.push(a[0].nxt[i]);
51     while(!q.empty())
52     {
53         int x=q.front();q.pop();
54         for(int i=0;i<26;++i)
55         {
56             if(a[x].nxt[i])
57             {
58                 a[a[x].nxt[i]].fal=a[a[x].fal].nxt[i];
59                 q.push(a[x].nxt[i]);
60             }
61             else a[x].nxt[i]=a[a[x].fal].nxt[i];
62         }
63     }
64     int tos=0,k=0,lens=s.length();
65     for(int i=0;i<lens;++i)
66     {
67         k=a[k].nxt[s[i]-'a'];
68         st[++tos]=k;
69         ans[tos]=s[i];
70         if(a[k].tag)//如果走到了一個單詞的結尾
71         {
72             tos-=a[k].d;//彈到這個單詞的開頭
73             k=st[tos];//修改k
74         }
75     }
76     for(int i=1;i<=tos;++i)
77     cout<<ans[i];//輸出
78     cout<<endl;
79     return 0;
80 }