你需要前置KMP知识。
题目大意
给出两个字符串S和T,每次从前往后找到S的一个子串A=T并将其删除。
空缺位依次向前补齐。
重复上述操作多次,直到S串中不含T串。输出最终的S串。
对于全部数据,1<=|T|<=|S|<=10^6,保证字符串中只出现小写字母。
题目分析
KMP...
什么???你打算每删去一次字串然后重头找一遍???
请告诉我你没T。
咱们要做一个灵活的胖子少年。
删去匹配成功的字串,然后接着删去字串的前一位继续与删去字串后面的字符匹配。
???你不知道怎么配???
开个数组记录匹配时每一个位置的k就ok啦。
然后删去之后的k变为删去子串的前一位的k就ok啦。
解释都放代码里了。
还是很好懂的。
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
char ans[1000010];//ans存答案
char a[1000010],b[1000010];
int next[1000010],kk[1000010];
//kk存匹配到该位时已匹配成功的长度
int main()
{
scanf("%s%s",a+1,b+1);
int la=strlen(a+1);
int lb=strlen(b+1);
int k=0; next[0]=next[1]=0;
for(int i=2;i<=lb;i++)
{
while(k>0&&b[k+1]!=b[i]) k=next[k];
if(b[k+1]==b[i]) k++;
next[i]=k;
}
k=0; int d=0;//存ans的长度
for(int i=1;i<=la;i++)
{
d++; ans[d]=a[i];
while(k>0&&b[k+1]!=ans[d]) k=next[k];
if(b[k+1]==ans[d]) k++; kk[d]=k;//记录好该位匹配成功的长度
if(k==lb) d-=lb,k=kk[d];//找到完全匹配的字串就删去它
//k变为 删去的 前一位 已匹配的长度,接着 删去字串后的字符 进行匹配
}
for(int i=1;i<=d;i++) printf("%c",ans[i]);
return 0;
}