SCU - 4438 (KMP)

这道题目要求在文本中找到并移除敏感词,利用KMP算法实现。输入包含多组测试,每组包含一个敏感词和一个文本,输出移除敏感词后的文本。题解中详细解释了KMP算法如何应用于该问题,通过维护一个辅助数组来避免回溯,并在完全匹配时更新文本。

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

SCU - 4438 (KMP)

Censor

frog is now a editor to censor so-called sensitive words (敏感词).

She has a long text pp. Her job is relatively simple – just to find the first occurence of sensitive word ww 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 11 string ww. The second line contains 11 string pp.

(1≤length of w,p≤5⋅1061≤length of w,p≤5⋅106, w,pw,p consists of only lowercase letter)

Output

For each test, write 11 string which denotes the censored text.

Sample Input

    abc
    aaabcbc
    b
    bbb
    abc
    ab

Sample Output

    a
    
    ab

题意:

​ 一个模板串tt,一个文本串ss,我们从文本穿ss中删除模板串tt,重复这一过程,直至文本串中不包含模板串 。输出最后的文本串。

思路:

​ 前置知识:KMP

i i i 指针指文本串将要匹配的位置,j 指针指模式串将要匹配的位置

​ kmp用来文本串与模板串匹配,如果匹配成功怎么办? i i i指针回退?不,我们可以维护另一个数组,作为匹配过程中的数组;每次文本串的 i i i 指针往后移动时,就将新的字符加入一个像栈一样的数组;如果当前是完全匹配模板串 t t tt tt,那么就将先从栈中弹出模板串 t t tt tt,再将新的字符加入栈即可。并且将 j j j指针指向栈中上次同样位置即可。

这样每次 i i i 指针文本串将要匹配的字符, j j j 指针指向模板串将要匹配的字符,栈中的字符是更新后的字符。

​ 这个过程就像模拟题目的操作一样。每次字符串向后移动,如果完全匹配,则删除字符串,并且重置 j j j指针。继续向后遍历字符

#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
char t[5000010],s[5000010],ans[50000010];
int net[5222010],maxj[5222210];
void getNext(const char s[],int ls,int net[])
{
    net[0]=-1;
    int j=0,k=-1;
    while(j<ls){
        if(k==-1||s[j]==s[k]) net[++j]=++k;
        else k=net[k];
    }
}
void solve(char tt[],char ss[])
{
    int lt=strlen(tt),ls=strlen(ss);
    int i=0,j=0,k=0;
    getNext(tt,lt,net);
    /*
    i j  maxj[] ans[]
    */
    ans[0]=s[0];
    maxj[0]=0;
    while(i<ls)
    {
        while(j!=-1&&ans[k]!=tt[j]) j=net[j];
        ++k,++i;++j;
        if(j>=lt){
            k-=lt;
            j=maxj[k];
        }
        ans[k]=ss[i];
        maxj[k]=j;
    }
}
int main(){
    while(cin>>t>>s)
    {
        solve(t,s);
        cout<<ans<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值