审查(银)
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 }