【BZOJ3942】Censoring [KMP]
Censoring
Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss]
Description
有一个S串和一个T串,长度均小于1,000,000,设当前串为U串,然后从前往后枚举S串一个字符一个字符往U串里添加,若U串后缀为T,则去掉这个后缀继续流程。
Input
第一行是S串,第二行是T串。
Output
输出一行,表示按照操作后得到的串。
Sample Input
whatthemomooofun
moo
moo
Sample Output
whatthefun
HINT
串长小于1000000。
Main idea
按照S串的顺序加入S串中的字符,一旦出现了一段和T串一样,则删去这一段,求最后得到的串。
Solution
运用KMP,我们显然只要先把T串加入到Stack里面,然后再按照S的顺序加入字符,每次求next(next[i]表示s[1…i]中最长的公共前后缀),显然next==T串长度的话删去相应长度即可。
Code
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdio> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cmath> 8 #include<bitset> 9 using namespace std; 10 11 const int ONE=2000001; 12 13 int n,m; 14 char a[ONE],b[ONE],Stack[ONE]; 15 int next[ONE],j,top; 16 17 int get() 18 { 19 int res=1,Q=1;char c; 20 while( (c=getchar())<48 || c>57 ) 21 if(c=='-')Q=-1; 22 res=c-48; 23 while( (c=getchar())>=48 && c<=57 ) 24 res=res*10+c-48; 25 return res*Q; 26 } 27 28 void Deal(int n,char a[],int PD) 29 { 30 for(int i=PD;i<=n;i++) 31 { 32 Stack[++top] = a[i]; 33 j=next[top-1]; 34 while(j && Stack[j+1] != Stack[top]) j=next[j]; 35 if(Stack[j+1] == Stack[top]) j++; 36 next[top] = j; 37 if(PD==1 && next[top]==m) top-=m; 38 } 39 } 40 41 int main() 42 { 43 scanf("%s",a+1); n=strlen(a+1); 44 scanf("%s",b+1); m=strlen(b+1); 45 Stack[++top]=b[1]; 46 Deal(m,b,2); Deal(n,a,1); 47 48 for(int i=m+1;i<=top;i++) 49 printf("%c",Stack[i]); 50 51 }