審查(銀)
阿新 • • 發佈:2018-10-31
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 }