一开始以为会是后缀数组之类的什么鬼东西,结果最后想了半天没想出来,结果想到hash秒出答案,所以有的时候应该考虑换一下思维方式。
因为题目要求查询和修改操作,维护一个splay,每个节点对应这个位置的字符和这棵子树的hash值,就能完成插入修改操作了,每一个询问的时候再二分最长前缀hash cheak就好了
然后。。。有一个函数忘了写return值结果BZOJ一直说我T,我改了很多常数还是T,最后才发现就过了郁闷
#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 200020
#define ls ch[u][0]
#define rs ch[u][1]
#define uint unsigned int
using namespace std;
int ch[maxn][2],val[maxn],fa[maxn],size[maxn],rt,tot,len;
uint pw[maxn],h[maxn];
void init(int u){
size[u]=size[ls]+size[rs]+1;
h[u]=(h[ls]*pw[size[rs]+1]+val[u]*pw[size[rs]]+h[rs]);
}
void Rotate(int u){
int d=u==ch[fa[u]][0];
int f=fa[u],ff=fa[f];
fa[u]=ff;if(ff!=0)ch[ff][f==ch[ff][1]]=u;
ch[f][!d]=ch[u][d];fa[ch[u][d]]=f;
ch[u][d]=f;fa[f]=u;
init(f);init(u);
}
void splay(int u,int k=0){
if(u==0)return;
while(fa[u]!=k){
int f=fa[u],ff=fa[f];
if(ff==k){Rotate(u);break;}
int d=u==ch[f][1],dd=f==ch[ff][1];
if(d==dd)Rotate(f);
else Rotate(u);
Rotate(u);
}
if(k==0)rt=u;
}
//插入一个符号是x 排在第k的字符
void insert(int u,int f,int x,int k,int d){
if(u==0){
tot++;
val[tot]=h[tot]=x,fa[tot]=f,size[tot]=1,ch[f][d]=tot;
splay(tot);
return;
}
if(k>size[ls]+1)insert(rs,u,x,k-size[ls]-1,1);
else insert(ls,u,x,k,0);
}
void change(int u,int k,int x){
if(k==size[ls]+1){
splay(u);val[u]=x;
init(u);
return;
}
if(k>size[ls]+1)change(rs,k-size[ls]-1,x);
else change(ls,k,x);
}
//找k的前缀和
uint query(int u,int k){
if(k==0)return 0;
if(k==size[ls]+1){
splay(u);
return h[ls]*pw[1]+val[u];
}
if(k>size[ls]+1)return query(rs,k-size[ls]-1);
return query(ls,k);
}
uint find(int a,int b){
if(b==0)return 0;
if(a+b-1>len)return -a;
return query(rt,a+b-1)-query(rt,a-1)*pw[b];
}
int solve(int a,int b){
int l=0,r=min(len-a,len-b)+1,ans;
while(l<=r){
int mid=l+r>>1;
if(find(a,mid)==find(b,mid))ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
char s[maxn],c[5];
int build(int l,int r,int f){
if(l>r)return 0;
tot++;
int u=tot;
if(l==r){
h[u]=val[u]=s[l]-'a',fa[u]=f,size[u]=1;
return u;
}
int mid=l+r>>1;
val[u]=s[mid]-'a',fa[u]=f;
ch[u][0]=build(l,mid-1,u);
ch[u][1]=build(mid+1,r,u);
init(u);
return u;
}
int main(){
pw[0]=1;
for(int i=1;i<=200000;i++)pw[i]=pw[i-1]*233;
scanf("%s",s+1);len=strlen(s+1);int a,b,n;
rt=build(1,len,0);
scanf("%d",&n);
while(n--){
scanf("%s",c);
if(c[0]=='Q'){
scanf("%d%d",&a,&b);
printf("%d\n",solve(a,b));
}else if(c[0]=='R'){
scanf("%d%s",&a,c);
change(rt,a,c[0]-'a');
}else {
scanf("%d%s",&a,c);
insert(rt,0,c[0]-'a',a+1,a+1>size[ch[rt][0]]+1);
len++;
}
}
return 0;
}