天天看点

字符串哈希 - SCU - 4438 栈维护哈希前缀和

题目链接:http://acm.scu.edu.cn/soj/problem.action?id=4438

题目大意:

给定一个字符串A和一个字符串B,如果如果B中存在A字符串,就在B中把A字符串去掉,输出最后去掉A字符串之后B字符串

字符串哈希 - SCU - 4438 栈维护哈希前缀和

用一个栈维护字符,如果栈的倒数|A|个数==B那么删除这你个数。

继续添加字符。

根据哈希值的计算公式:(左为高位。相当于p进制的数。)

字符串哈希 - SCU - 4438 栈维护哈希前缀和

根据子串哈希值的计算公式:

字符串哈希 - SCU - 4438 栈维护哈希前缀和

那么根据当前栈顶的元素,就能推导下个字符的哈希值。

#include<bits/stdc++.h>

#define ull unsigned long long
using namespace std;
const int maxn=5000006;

ull base =131;
ull g[maxn];
ull p[maxn];

ull Hash(char s[])
{
    int n=strlen(s+1);
    g[0]=0;
    for(int i=1;i<=n;i++)
    {
        g[i]=g[i-1]*base+s[i];
    }
    return g[n];
}

void getp()
{
    p[0]=1;
    for(int i=1;i<=maxn;i++)
    {
        p[i]=p[i-1]*base;
    }
}

ull getLR(int l, int r)//取出T里l - r里面的字符串的hash值
{
    return g[r]-g[l-1]*p[r-l+1];
}

char s[5000060], t[5000060], ans[5000060];

int main()
{
    getp();
    while(~scanf("%s%s",s+1,t+1))
    {
        int Ls=strlen(s+1), Lt=strlen(t+1);
        ull key = Hash(s);
        int tot=0;
        for(int i=1;i<=Lt;i++)
        {
            ans[++tot]=t[i];
            g[tot]=g[tot-1]*base+t[i];
            if(tot>=Ls&&g[tot]-g[tot-Ls]*p[Ls]==key)
            {
                tot-=Ls;
            }
        }
        ans[tot+1]=0;
        printf("%s\n",ans+1);
    }

    return 0;
}