【题目描述】
FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S。他有一个包含n个单词的列表,列表里的n个单词
记为t_1...t_N。他希望从S中删除这些单词。
FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中
没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词
FJ注意到列表中的单词不会出现一个单词是另一个单词子串的情况,这意味着每个列表中的单词在S中出现的开始位置是互不相同的
请帮助FJ完成这些操作并输出最后的S
【样例输入】
begintheescapexecutionatthebreakofdawn
2
escape
execution
2
escape
execution
【样例输出】
beginthatthebreakofdawn
【题解】
和p3942一样的思路(连题目名字都一样),建议先写p3942,我可以说这个东西叫可持久化AC自动机吗?(并没有这个东西)
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cstdlib>
5 #include<ctime>
6 #include<cmath>
7 #include<algorithm>
8 using namespace std;
9 #define MAXN 100010
10 int n,cnt,top,end[MAXN],fail[MAXN],deep[MAXN],f[MAXN],q[MAXN],stack[MAXN],tr[MAXN][27];
11 char b[MAXN],ch[MAXN];
12 void insert()
13 {
14 int now=0,len=strlen(ch+1);
15 for(int i=1;i<=len;i++)
16 {
17 if(!tr[now][ch[i]-'a']) tr[now][ch[i]-'a']=++cnt;
18 now=tr[now][ch[i]-'a'];
19 }
20 end[now]=max(end[now],len);
21 }
22 void build()
23 {
24 int head=0,tail=0;
25 for(int i=0;i<26;i++) if(tr[0][i]) q[++tail]=tr[0][i];
26 while(++head<=tail)
27 {
28 int x=q[head];
29 for(int i=0;i<26;i++)
30 {
31 if(!tr[x][i]) tr[x][i]=tr[fail[x]][i];
32 else {fail[tr[x][i]]=tr[fail[x]][i]; q[++tail]=tr[x][i];}
33 }
34 }
35 }
36 void find()
37 {
38 int len=strlen(b+1);
39 for(int i=1,x=0;i<=len;i++)
40 {
41 f[i]=tr[f[stack[top]]][b[i]-'a'];
42 stack[++top]=i;
43 top-=end[f[i]];
44 }
45 }
46 int main()
47 {
48 //freopen("cin.in","r",stdin);
49 //freopen("cout.out","w",stdout);
50 scanf("%s%d",b+1,&n);
51 for(int i=1;i<=n;i++) {scanf("%s",ch+1); insert();}
52 build();
53 find();
54 for(int i=1;i<=top;i++) printf("%c",b[stack[i]]);
55 return 0;
56 }
来源:https://www.cnblogs.com/chty/p/6006415.html