Censor SCU - 4438 (字符串hash)

这是一个关于字符串处理的问题,要求帮助编辑Censor SCU找到并删除文本中首次出现的敏感词。给定两个字符串w和p,长度都在500万以内且仅包含小写字母。题目描述要求删除p中首次出现的与w相同的子串,并给出样例解答。解决方法是使用字符串hash,检查p中长度与w相等的子串,若hash值相同则删除该子串,最终得到censored文本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值