[USACO15FEB] Censoring

题目链接

这道题就是说
我们要在S中删掉所有T,但是删掉之后可能又有了T,我们就一直删直到删完

很明显,第一次删肯定需要kmp(自动AC机应该也可以吧…)

那么我们可以想到,当我们匹配完之后,我们再往前看,有没有生成新的T,那么访问此前的一个位置(并且是倒序访问),所以我们可以开一个栈,把之前访问过的每一个元素都加进去,当匹配成功,弹出栈顶的 t |t| 个元素, j j 变成栈顶元素所匹配的值,最后所有留在栈里的元素,就是所有剩下的字符

当然你也可能会问,我们怎么知道跳回栈顶的时候栈顶i对应的j呢?这个简单,开个数组记一下就好了

我们在来理一下思路:

1.正常做kmp,遇到一个字符往栈里压
2.匹配成功,弹出栈顶的|t|个元素,j变成栈顶的i对应的j
3.最后栈里面的所有的都是最后存在的字符
# include <cstdio>
# include <algorithm>
# include <cstring>
# include <cmath>
# include <climits>
# include <iostream>
# include <string>
# include <queue>
//# include <stack>
# include <vector>
# include <set>
# include <map>
# include <cstdlib>
# include <ctime>
using namespace std;

# define Rep(i,a,b) for(int i=a;i<=b;i++)
# define _Rep(i,a,b) for(int i=a;i>=b;i--)
# define RepG(i,u) for(int i=head[u];~i;i=e[i].next)

typedef long long ll;
const int N=1e6+5;
const int inf=0x7fffffff;
const double eps=1e-7;
template <typename T> void read(T &x){
	x=0;int f=1;
	char c=getchar();
	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
	for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-'0';
	x*=f;
}

char s[N],t[N];
int ls,lt;
int stack[N],top;
int nxt[N],pipi[N];

void init(){//kmp预处理不讲 
	for(int i=2,j=0;i<=lt;i++){
		while(j&&t[i]!=t[j+1])j=nxt[j];
		if(t[i]==t[j+1])j++;
		nxt[i]=j;
	}
}

void kmp(){
	for(int i=1,j=0;i<=ls;i++){
		while(j&&s[i]!=t[j+1])j=nxt[j];
		if(s[i]==t[j+1])j++;//正常kmp
		pipi[i]=j;//储存对应位置的字符
		stack[++top]=i;//往栈里压
		if(j==lt){top-=lt,j=pipi[stack[top]];}//匹配成功,弹栈
	}
}

int main()
{
	scanf("%s%s",s+1,t+1);
	ls=strlen(s+1),lt=strlen(t+1);
	init();
	kmp();
	Rep(i,1,top)printf("%c",s[stack[i]]);
	puts("");
	return 0;	
}
发布了45 篇原创文章 · 获赞 52 · 访问量 9647

猜你喜欢

转载自blog.csdn.net/devout_/article/details/104169507