审查(银)

FJ把杂志上所有的文章摘抄了下来并把它变成了一个长度不超过10^5的字符串S。他有一个包含n个单词的列表,列表里的n个单词记为t_1...t_N。他希望从S中删除这些单词。

FJ每次在S中找到最早出现的列表中的单词(最早出现指该单词的开始位置最小),然后从S中删除这个单词。他重复这个操作直到S中没有列表里的单词为止。注意删除一个单词后可能会导致S中出现另一个列表中的单词

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

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

 

这个删完后要用链表连接,但是匹配串应该退回到哪里呢,

就是在每次枚举到一个i的时候,都记录此时的j,表示第i位往前最多可以和匹配串的前j位匹配,以便删完后往前跳的时候,匹配串应该跳到哪里

 

KMP的细节总是很多,要背过啦

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<vector>
 7 #include<stack>
 8 #include<queue>
 9 #include<map>
10 #include<set>
11 using namespace std;
12 const int maxn=1e6+7;
13 char s[maxn],t[maxn];
14 int lens,lent;
15 int nxt[maxn],mth[maxn],l[maxn],r[maxn];
16 void pre(){
17   nxt[1]=0;int j=0;
18   for(int i=1;i<lent;i++){
19     while(j&&t[i+1]!=t[j+1]) j=nxt[j];
20     if(t[i+1]==t[j+1]) j++;
21     nxt[i+1]=j;
22   }
23 }
24 int main(){
25   scanf("%s",s+1);scanf("%s",t+1);
26   lens=strlen(s+1);lent=strlen(t+1);
27   pre();
28   for(int i=1;i<=lens;i++) l[i]=i-1,r[i]=i+1;
29   r[0]=1;int j=0;
30   for(int i=0;i<lens;i=r[i]){
31     mth[i]=j;
32     while(j&&s[r[i]]!=t[j+1]) j=nxt[j];
33     if(s[r[i]]==t[j+1]) j++;
34     if(j==lent){
35       int tmp=r[r[i]];
36       for(int k=1;k<lent;k++) i=l[i];
37       l[tmp]=i;r[i]=tmp;
38       j=mth[i];i=l[i];
39     }
40   } 
41   for(int i=r[0];i<=lens;i=r[i]){
42     cout<<s[i];
43   }cout<<endl;
44   return 0;
45 } 

 

posted @ 2018-10-31 20:25  lcan  阅读(150)  评论(0编辑  收藏  举报