这道题就是说
我们要在S中删掉所有T,但是删掉之后可能又有了T,我们就一直删直到删完
很明显,第一次删肯定需要kmp(自动AC机应该也可以吧…)
那么我们可以想到,当我们匹配完之后,我们再往前看,有没有生成新的T,那么访问此前的一个位置(并且是倒序访问),所以我们可以开一个栈,把之前访问过的每一个元素都加进去,当匹配成功,弹出栈顶的 个元素, 变成栈顶元素所匹配的值,最后所有留在栈里的元素,就是所有剩下的字符
当然你也可能会问,我们怎么知道跳回栈顶的时候栈顶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;
}