【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

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 }
View Code
原文地址:https://www.cnblogs.com/BearChild/p/6479502.html