题意:给出一字符串,每次:
1、询问从第x个和第y个字符开始的字符串的lcq
2、修改某字符
3、在某字符后插入一字符(可以在开头)
思路:发现又插入操作之后应该就是平衡树了,所以想splay。。
然后lcq改为判断型问题(二分长度)
每个节点记录一下它和它子树构成字符串的hash值。
每次二分时判断一发就好
感觉代码量好大。。调了好久。。
代码:
#include <bits/stdc++.h>
#define N 200009
#define mod 9875321
#define ll long long
using namespace std;
char str[N],ch[10];
int m,x,y,n,val[N],hash[N],fa[N],root,cnt,p[N];
struct Node
{
int sz,val,hash;
int ch[2],pnt;
Node(){}
}a[2000003];
int Rank_get_num(int rank)
{
int now=root;
while (1)
{
if (a[a[now].ch[0]].sz+1==rank)
{
return now;
break;
}
else
if (a[a[now].ch[0]].sz+1<rank)
rank-=a[a[now].ch[0]].sz+1,now=a[now].ch[1];
else now=a[now].ch[0];
}
}
void updata(int x)
{
int ls=a[x].ch[0],rs=a[x].ch[1];
a[x].sz=a[ls].sz+a[rs].sz+1;
a[x].hash=(a[ls].hash+(ll)a[x].val*p[a[ls].sz]%mod+(ll)p[a[ls].sz+1]*a[rs].hash%mod)%mod;
}
void rotate(int x,bool d)
{
int y=a[x].pnt;
a[y].ch[!d]=a[x].ch[d];
if (a[x].ch[d]!=0) a[a[x].ch[d]].pnt=y;
a[x].pnt=a[y].pnt;
if (a[y].pnt!=0)
{
if (y==a[a[y].pnt].ch[d]) a[a[y].pnt].ch[d]=x;
else a[a[y].pnt].ch[!d]=x;
}
a[x].ch[d]=y;
a[y].pnt=x;
updata(y);
updata(x);
}
void splay(int x,int target)
{
int y;
while (a[x].pnt!=target)
{
y=a[x].pnt;
if (x==a[y].ch[0])
{
if (a[y].pnt!=target&&y==a[a[y].pnt].ch[0]) rotate(y,true);
rotate(x,true);
}
else
{
if (a[y].pnt!=target&&y==a[a[y].pnt].ch[1]) rotate(y,false);
rotate(x,false);
}
}
if (target==0) root=x;
}
void Insert(int x,int y)
{
int x1=Rank_get_num(x+1);
int x2=Rank_get_num(x+2);
splay(x1,0);
splay(x2,x1);
int x3=++cnt;
a[x2].ch[0]=x3;
a[x3].pnt=x2;
a[x3].val=y;
updata(x3);
updata(x2);
updata(x1);
}
void build(int l,int r,int fa)
{
if (l>r) return;
if (l==r)
{
a[l].hash=a[l].val=str[l]-'a'+1;
a[l].pnt=fa;
a[l].sz=1;
if (l<fa) a[fa].ch[0]=l;
else a[fa].ch[1]=l;
return;
}
int mid=l+r>>1;
build(l,mid-1,mid);
build(mid+1,r,mid);
a[mid].pnt=fa;
a[mid].val=str[mid]-'a'+1;
updata(mid);
if (mid<fa) a[fa].ch[0]=mid;
else a[fa].ch[1]=mid;
}
int qry(int x,int len)
{
int x1=Rank_get_num(x);
int x2=Rank_get_num(x+len+1);
splay(x1,0);
splay(x2,root);
return a[a[x2].ch[0]].hash;
}
int solve(int x,int y)
{
int l=1,r=min(cnt-x-1,cnt-y-1),ans=0;
while (l<=r)
{
int mid=l+r>>1;
if (qry(x,mid)==qry(y,mid)) ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
int main()
{
p[0]=1;
for (int i=1;i<=150004;i++) p[i]=p[i-1]*27%mod;
scanf("%s",str+2);
n=strlen(str+2);
str[n+2]=127;
build(1,n+2,0);
root=(3+n)>>1;
cnt=n+2;
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%s%d",ch+1,&x);
if (ch[1]=='I') scanf("%s",ch+1),Insert(x,ch[1]-'a'+1);
else
if (ch[1]=='R')
{
scanf("%s",ch+1);
int x1=Rank_get_num(x+1);
splay(x1,0);
a[root].val=ch[1]-'a'+1;
updata(root);
}
else
{
int y;
scanf("%d",&y);
printf("%d\n",solve(x,y));
}
}
return 0;
}