题目描述
题解
用splay维护一段区间的hash值,然后每一次查询的时候二分+判定就行了
算hash值update的时候只需要维护一下左右子树的大小
注意插入一个前驱一个后继,编号不要算错了
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define N 150005
#define UL unsigned long long
char s[N];
int n,root,m,x,y,px,py,ans;
int f[N],ch[N][2],size[N];char key[N];
UL mi[N],hash[N];
const UL S=2000001001LL;
void update(int x)
{
UL now=0;size[x]=0;
if (ch[x][1]) now+=hash[ch[x][1]],size[x]+=size[ch[x][1]];
now+=(UL)key[x]*mi[size[x]];++size[x];
if (ch[x][0]) now+=hash[ch[x][0]]*mi[size[x]],size[x]+=size[ch[x][0]];
hash[x]=now;
}
int build(int l,int r,int fa)
{
if (l>r) return 0;
int mid=(l+r)>>1;
f[mid]=fa;key[mid]=s[mid-1];
int ls=build(l,mid-1,mid);
int rs=build(mid+1,r,mid);
ch[mid][0]=ls,ch[mid][1]=rs;
update(mid);
return mid;
}
int get(int x)
{
return ch[f[x]][1]==x;
}
void rotate(int x)
{
int old=f[x],oldf=f[old],wh=get(x);
ch[old][wh]=ch[x][wh^1];
if (ch[old][wh]) f[ch[old][wh]]=old;
ch[x][wh^1]=old;
f[old]=x;
if (oldf) ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
update(old);
update(x);
}
void splay(int x,int tar)
{
for (int fa;(fa=f[x])!=tar;rotate(x))
if (f[fa]!=tar)
rotate((get(x)==get(fa))?fa:x);
if (!tar) root=x;
}
int find(int x)
{
int now=root;
while (1)
{
if (ch[now][0]&&size[ch[now][0]]>=x) now=ch[now][0];
else
{
if (ch[now][0]) x-=size[ch[now][0]];
if (x==1) return now;
--x;
now=ch[now][1];
}
}
}
bool check(int mid)
{
// [x,x+mid-1]
int aa=find(x+mid+1);
splay(px,0);
splay(aa,px);
UL hx=hash[ch[ch[root][1]][0]];
// [y,y+mid-1]
int bb=find(y+mid+1);
splay(py,0);
splay(bb,py);
UL hy=hash[ch[ch[root][1]][0]];
return hx==hy;
}
int dvd()
{
int l=1,r=n-y+1,mid,ans=0;
while (l<=r)
{
mid=(l+r)>>1;
if (check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int main()
{
mi[0]=1;for (int i=1;i<=100000;++i) mi[i]=mi[i-1]*S;
scanf("%s",s+1);n=strlen(s+1);
s[0]=s[n+1]='$';
root=build(1,n+2,0);
scanf("%d",&m);
for (int i=1;i<=m;++i)
{
char opt=getchar();
while (opt!='Q'&&opt!='R'&&opt!='I') opt=getchar();
if (opt=='Q')
{
scanf("%d%d",&x,&y);
if (x>y) swap(x,y);
// x y
px=find(x);
py=find(y);
ans=dvd();
printf("%d\n",ans);
}
else if (opt=='R')
{
int x;char d;
scanf("%d %c",&x,&d);
// x
int aa=find(x+1);
splay(aa,0);
key[root]=d;
update(root);
}
else if (opt=='I')
{
int x;char d;
scanf("%d %c",&x,&d);
// [x,x+1]
int aa=find(x+1);
int bb=find(x+2);
splay(aa,0);
splay(bb,aa);
++n;
key[n+2]=hash[n+2]=d;size[n+2]=1;
f[n+2]=ch[root][1];ch[ch[root][1]][0]=n+2;
update(ch[root][1]);
update(root);
}
}
}