1. 程式人生 > >審查(銀)

審查(銀)

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 }