分析:
类似于Splay维护序列,Splay的每个节点维护其子树所表示字符串的哈希值。
询问时二分答案即可。
代码:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <cmath>
#include <algorithm>
typedef long long LL;
inline int read(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x;
}
const int MAXN=100005;
const LL MOD=998244353;
const LL Base=31;
char str[MAXN];
int m,root,tot;
LL pw[MAXN];
struct Splay{
int ch[2],fa;
int val;
int siz;
LL hsh;
}a[MAXN];
inline void pre_process(){
pw[0]=1;
for(int i=1;i<=MAXN-1;i++)
pw[i]=pw[i-1]*Base;
}
#define lc a[x].ch[0]
#define rc a[x].ch[1]
inline void pushup(int x){
a[x].siz=a[lc].siz+a[rc].siz+1;
a[x].hsh=a[rc].hsh+a[x].val*pw[a[rc].siz]+a[lc].hsh*pw[a[rc].siz+1];
}
int build(int l,int r,int pre){
if(l>r) return 0;
int x=++tot;
int mid=((l+r)>>1);
a[x].fa=pre;
a[x].val=str[mid]-'a';
lc=build(l,mid-1,x);
rc=build(mid+1,r,x);
pushup(x);
return x;
}
inline void rotate(int x){
int y=a[x].fa,z=a[y].fa,f=(a[y].ch[1]==x),g=a[x].ch[f^1];
if(z) a[z].ch[a[z].ch[1]==y]=x;
a[x].ch[f^1]=y;
a[y].ch[f]=g;
if(g) a[g].fa=y;
a[y].fa=x;
a[x].fa=z;
pushup(y);
pushup(x);
}
inline void splay(int x,int tp){
while(a[x].fa!=tp){
int y=a[x].fa,z=a[y].fa;
if(a[y].fa!=tp){
if((a[y].ch[0]==x)==(a[z].ch[0]==y)) rotate(y);
else rotate(x);
}
rotate(x);
}
if(tp==0) root=x;
}
inline int kth(int k){
int x=root;
while(1){
if(a[lc].siz>=k) x=lc;
else if(a[lc].siz+1==k) return x;
else{
k-=a[lc].siz+1;
x=rc;
}
}
}
inline LL query(int x,int y){
// std::cout<<x<<" "<<y<<std::endl;
int xx=kth(x-1),yy=kth(y+1);
splay(xx,0);
splay(yy,xx);
return a[a[yy].ch[0]].hsh;
}
inline int lcq(int x,int y){
if(x<y) std::swap(x,y);
int l=0,r=tot-x,ret=0;
while(l<=r){
// std::cout<<l<<" "<<r<<std::endl;
int mid=((l+r)>>1);
if(query(x,x+mid-1)==query(y,y+mid-1)) ret=mid,l=mid+1;
else r=mid-1;
}
return ret;
}
inline void upd(int x,int ch){
int xx=kth(x);
splay(xx,0);
a[xx].val=ch;
pushup(xx);
}
inline void ins(int x,int ch){
int xx=kth(x),yy=kth(x+1);
splay(xx,0);
splay(yy,xx);
a[yy].ch[0]=++tot;
a[tot].fa=yy;
a[tot].val=ch;
//...
splay(tot,0);
}
void write(int x){
if(lc) write(lc);
std::cout<<char(a[x].val+'a'==0?'#':a[x].val+'a');
if(rc) write(rc);
}
int main(){
pre_process();
scanf("%s",str+2);
int len=strlen(str+2);
len+=2;
// std::cout<<len<<std::endl;
// std::cout<<str[2]<<" "<<str[12]<<std::endl;
str[1]=str[len]='\0';
root=build(1,len,0);
scanf("%d",&m);
while(m--){
// write(root);std::cout<<std::endl;
char opt=getchar();
while(!isalpha(opt)) opt=getchar();
if(opt=='Q'){
int x=read(),y=read();
printf("%d\n",lcq(x+1,y+1));
}
else if(opt=='R'){
int x=read();char ch=getchar();
while(!isalpha(ch)) ch=getchar();
upd(x+1,ch-'a');
}
else{
int x=read();char ch=getchar();
while(!isalpha(ch)) ch=getchar();
ins(x+1,ch-'a');
}
}
return 0;
}