bzoj 3942: [Usaco2015 Feb]Censoring(题解)

题目描述


Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so they have plenty of material to read while waiting around in the barn during milking sessions. Unfortunately, the latest issue contains a rather inappropriate article on how to cook the perfect steak, which FJ would rather his cows not see (clearly, the magazine is in need of better editorial oversight).
FJ has taken all of the text from the magazine to create the string S of length at most 10^6 characters. From this, he would like to remove occurrences of a substring T to censor the inappropriate content. To do this, Farmer John finds the first occurrence of T in S and deletes it. He then repeats the process again, deleting the first occurrence of T again, continuing until there are no more occurrences of T in S. Note that the deletion of one occurrence might create a new occurrence of T that didn’t exist before.
Please help FJ determine the final contents of S after censoring is complete
有一个S串和一个T串,长度均小于1,000,000,设当前串为U串,然后从前往后枚举S串一个字符一个字符往U串里添加,若U串后缀为T,则去掉这个后缀继续流程。
这里写图片描述

题解:

首先我们要先读清题意,在给定的文本串中删去模式串,注意,删去后文本串会像我们玩的消消乐那样,后面的字符串会向前面靠拢,注意,这时可能又会出现新形成的模式串,这就让处理变得麻烦起来,我们再来看题目,“然后从前往后枚举S串一个字符一个字符往U串里添加”,一个一个添加,有没有想到什么???没错,我们可以维护一个栈来帮助我们进行操作,在栈中跑KMP的时候要注意,当你删去一个模式串的时候,要将j的值还原到此时栈顶的next值,也就是我们要记录每个位置的next值。

蒟蒻代码:

//By Bibi
///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
///             __.'              ~.   .~              `.__
///           .'//                  \./                  \\`.
///        .'//                     |                     \\`.
///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
///     .'//.-"                 `-.  |  .-'                 "-.\\`.
///   .'//______.============-..   \ | /   ..-============.______\\`.
/// .'______________________________\|/______________________________`.
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define dep(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
const int MAXN=1000010;
char s[MAXN],t[MAXN];
int len_s,len_t;
char zhan[MAXN];
int top;
int f[MAXN];
int next[MAXN];
int read(){
    int sum=0,flag=1;
    char c;
    for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=-1;
    for(;c>='0'&&c<='9';c=getchar())sum=(sum<<1)+(sum<<3)+c-'0';
    return sum*flag;
} 
void init(){
    scanf("%s",s+1);
    scanf("%s",t+1);
    len_s=strlen(s+1);
    len_t=strlen(t+1);
}
void yuchuli(){//处理处next数组 
    int j=0;
    next[1]=0;
    rep(i,2,len_t){
        while(j&&t[i]!=t[j+1]) j=next[j];
        if(t[i]==t[j+1]) ++j;
        next[i]=j; 
    }
}
void work(){
    int j=0;
    rep(i,1,len_s){
        zhan[++top]=s[i];//字符进栈 
        while(j&&(s[i]!=t[j+1]||j==len_t)) j=next[j];//KMP 跳跳跳 
        if(s[i]==t[j+1]) ++j;
        f[top]=j;//记录每个位置的 next 
        if(j==len_t){//找到模式串 
            top-=len_t;//将其清理出栈 
            j=f[top];//将j的值还原到删去后栈顶的值 
        }
    }
    rep(i,1,top) putchar(zhan[i]);
}
int main(){
    init();
    yuchuli();
    work();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/bbbblzy/article/details/79833340