Censoring
https://loj.ac/problem/10048
题目描述
给出两个字符串\(S\)和\(T\),要求不断从\(S\)中删除\(T\),删除\(T\)后空缺为补齐,求删完后的字符串。
思路
单字符串匹配,显然我们可以用\(KMP\)。先跑一遍\(KMP\)的板子,预处理匹配串。接下来就是匹配,由于可能会存在补齐空位后出现的匹配串,而多次扫描不知道要扫描几次,我们可以用栈储存每个字符的位置,如果一个地方匹配完成,我们就出栈\(m\)个,再从栈顶开始匹配,最后输出保留在栈中的元素即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e6+10;
char s[MAXN],t[MAXN];
int pre[MAXN],f[MAXN],st[MAXN];
int main()
{
scanf(" %s %s",s+1,t+1);
int n=strlen(s+1),m=strlen(t+1);
pre[1]=0;
int j=0;
for(int i=1;i<m;i++)
{
while(j>0&&t[i+1]!=t[j+1])j=pre[j];
if(t[i+1]==t[j+1])j++;
pre[i+1]=j;
}
j=0;int top=0;
for(int i=0;i<n;i++)
{
while(j>0&&s[i+1]!=t[j+1])j=pre[j];
if(s[i+1]==t[j+1])j++;
f[i+1]=j;
st[++top]=i+1;
if(j==m)
{
top-=m;
j=f[st[top]];
}
}
for(int i=1;i<=top;i++)
putchar(s[st[i]]);
return 0;
}