Censor SCU - 4438 (字符串hash)
题目描述
Censor
frog is now a editor to censor so-called sensitive words (敏感词).
She has a long text p. Her job is relatively simple – just to find the first occurence of sensitive word w and remove it.
frog repeats over and over again. Help her do the tedious work.
Input
The input consists of multiple tests. For each test:
The first line contains 1 string w. The second line contains 1 string p.
(1≤length of w,p≤5⋅106, w,p consists of only lowercase letter)
Output
For each test, write 1 string which denotes the censored text.
Sample Input
abc
aaabcbc
b
bbb
abc
ab
Sample Output
a
ab
题意
多组输入两个字符串(1<=长度<=5*1e6),字符串都由小写字母组成。要求删除第二个字符串的子串(这个子串等于第一个字符串)。
注:第一个字符串在被删去子串后,剩余部分继续连接在一起。
如第一组样例
abc
aaabcbc
过程:aaabcbc—->aabc—->a
思路
先用字符串hash出第一个字符串的值,再对第二个字符串hash,判断子串与第一个字符串长度相同时的hash值是否相同,若相同则删除(用栈维护的思想,移动下标即可,最后栈中的字符串即为答案)
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll; //unsigned 定义的可以自动取模
const int maxn=5000010;
char s1[maxn],s2[maxn],ans[maxn];
const ll HASH=1e5+7; //在hash中常用一个比较大的素数
int n,m; //分别为两个字符串的长度
ll multi[maxn]; //用于hash的数组
ll st[maxn],sum;
void init() //预处理
{
multi[0]=1;
int i;
for(i=1;i<maxn;i++)
multi[i]=multi[i-1]*HASH;
}
inline bool check(int pos)
{
if(pos>=n){ //取长度为n的子串的hash值与第一个字符串的hash值比较
if(st[pos]-st[pos-n]*multi[n]==sum)
return true;
}
return false;
}
int main()
{
init();
while(scanf("%s %s",s1,s2)!=EOF){ //多组输入
n=strlen(s1);
m=strlen(s2);
int i,j,top=0;
sum=0; //第一个字符串的hash值
for(i=0;i<n;i++){
sum=sum*HASH+s1[i]; //用预处理好的数组对第一个字符串进行hash
}
st[0]=0;
for(i=0;i<m;i++){
ans[top++]=s2[i];
st[top]=st[top-1]*HASH+s2[i];
if(check(top)) //判断
top-=n; //移动下标,表示删除长度为n的子串
}
//printf("ans:");
for(i=0;i<top;i++)
printf("%c",ans[i]);
printf("\n");
}
return 0;
}
/*
abc
aaabcbc
b
bbb
abc
ab
*/