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