其他分享
首页 > 其他分享> > URAL - 1989 【线段树||树状数组 Hash 回文串】

URAL - 1989 【线段树||树状数组 Hash 回文串】

作者:互联网

URAL - 1989 【线段树||树状数组 Hash 回文串】

题目链接

题目描述:给你一个字符串(|s|<=1e5),有Q次询问,1可以单点修改字符,2或者给你区间L,R,问你这个字串是不是回文串。(Q<=1e5)
思路:暴力必然超时。如果没有点修改,怎么快速判断子串是不是回文串?当然是hash了,类似于一个前缀和的求取。然后点修改会影响hash值,每次修改之后就要重新O(n)更新吗?貌似线段树或者树状数组
对于一个字符串a[0],a[1],…,a[n-1] 它对应的哈希函数为a[0]+a[1]*K + a[2]*K^2 +…+a[n-1]*K^(n-1)
再维护一个从右往左的哈希值:a[0]*K^(n-1) + a[1]*K^(n-2) +…+a[n-1]
若是回文串,则左右的哈希值会相等。而左右哈希值相等,则很大可能这是回文串。
若出现误判,可以再用一个K2,进行双哈希判断,可以减小误判概率。
实现上,哈希值最好对某个质数取余数,这样分布更均匀。

在这里插入图片描述

代码实现

#include<bits/stdc++.h>
using namespace std;
const int base=131;
const int maxn=1e5+5;
const int mod=1e9+7;
int Hash[maxn],x,y,pos,n;
char s[maxn];
char val[2],op[2];
struct node
{
    int l,r,hashl,hashr;
} a[maxn<<2];
void init()
{
    Hash[0]=1;
    for(int i=1; i<=n; i++)
        Hash[i]=Hash[i-1]*base;
}
void pushup(int lnum,int rnum,int i)
{
    a[i].hashl=a[i*2].hashl+a[i*2+1].hashl*Hash[lnum];
    a[i].hashr=a[i*2+1].hashr+a[i*2].hashr*Hash[rnum];
}
void build(int l,int r,int i)
{
    a[i].l=l,a[i].r=r;
    if(l==r)
    {
        a[i].hashl=a[i].hashr=(s[l]-'a');
        return ;
    }
    int mid=(l+r)/2;
    build(l,mid,i*2);
    build(mid+1,r,i*2+1);
    pushup(mid-l+1,r-mid,i);
}
void update(int i,int pos,int val,int l,int r)
{
    if(l==r)
    {
        a[i].hashl=a[i].hashr=val;
        return ;
    }
    int mid=(l+r)/2;
    if(pos<=mid)
        update(i*2,pos,val,l,mid);
    else
        update(i*2+1,pos,val,mid+1,r);
    pushup(mid-l+1,r-mid,i);
}

node query(int i,int l,int r,int L,int R)
{
    if(L<=l&&R>=r)
    {
        return a[i];
    }
    int mid=(l+r)/2,flag=0;
    node ans,ans2,ans1,ans3;
    if(L<=mid)
        ans1=query(i*2,l,mid,L,R),flag+=1;
    if(R>mid)
        ans2=query(i*2+1,mid+1,r,L,R),flag+=2;
    if(flag==1)
        return ans1;
    else if(flag==2)
        return ans2;
    else if(flag==3)
    {
        ans3.hashl=ans1.hashl+ans2.hashl*Hash[mid-max(L,l)+1];
        ans3.hashr=ans2.hashr+ans1.hashr*Hash[min(R,r)-mid];
        return ans3;
    }
}
int main()
{

    scanf("%s",s+1);
    n=strlen(s+1);init();
    build(1,n,1);
    int q;
    scanf("%d",&q);
    while(q--)
    {
        scanf("%s",op);
        if(op[0]=='p')
        {
            scanf("%d%d",&x,&y);
            node ans=query(1,1,n,x,y);
            if(ans.hashl==ans.hashr)
                puts("Yes");
            else
                puts("No");
        }
        else
        {
            scanf("%d %s",&pos,val);
            update(1,pos,val[0]-'a',1,n);
        }
    }


}

标签:Hash,int,hashl,scanf,1989,哈希,hashr,URAL
来源: https://blog.csdn.net/qq_43653111/article/details/100732190