题目描述
现在给定一个你很讨厌的字符串 A 和另外一个字符串 B,请删除在 B 中出现的所有 A。
请注意:有可能在删除一个 A 后导致新的 A 出现,此时请继续删除,直到没有 A。
输入格式
输入为多组数据,请处理到 EOF。
对于每组数据:
第一行为你很讨厌的字符串 A,第二行为另外一个字符串 B,均仅包括小写字母。
保证 A串 和 B串 的长度不超过 5000000 且 A、B 均不为空串。
输出格式
对于每组数据,输出一行,即完成删除后的字符串。
样例输入
abc
aaabcbc
b
bbb
abc
ab
样例输出
a
ab
样例解释
第一组数据的删除过程:
aaabcbc -> aa[abc]bc -> aabc -> a[abc] -> a
第二组数据的删除过程:
bbb -> [b]bb -> bb -> [b]b -> b -> [b] ->
第三组数据由于讨厌的字符串并没有出现,所以没有被删除任何一个部分。
思路:开始毫无思路,后来百度他人题解看到了别人的标签,栈,瞬间思路就来了,就像括号匹配一样,这个题目也可以这样做,只是判断是否匹配复杂度很高,这个时候就可以用到哈希,用O(1)的时间判断两个字符串是否匹配,所以总复杂度就是O(n)。
代码:
#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define Max 5000005
const LL mod=1e9+7;
const ULL base=131;
const LL LL_MAX=9223372036854775807;
using namespace std;
ULL Hash[Max],p[Max];
char Stack[Max],a[Max],b[Max];
inline ULL getHashRange(int l,int r){
return Hash[r]-Hash[l-1]*p[r-l+1];
}
void init(){
p[0]=1;
for(int i=1;i<Max;i++)
p[i]=p[i-1]*base;
}
int main()
{
init();
while(scanf("%s%s",a+1,b+1)==2){
memset(Stack,0,sizeof(Stack));
int lena=strlen(a+1),lenb=strlen(b+1);
ULL Hasha=0;
for(int i=1;i<=lena;i++)
Hasha=Hasha*base+a[i];
int top=1;
for(int i=1;i<=lenb;i++){
Hash[top]=Hash[top-1]*base+b[i];
Stack[top]=b[i];
if(top>=lena){
ULL t=getHashRange(top-lena+1,top);
if(t==Hasha){
top=max(1,top-lena+1);
}else
top++;
}
else
top++;
}
Stack[top]='\0';
printf("%s\n",Stack+1);
}
return 0;
}