题目传送门
题目大意:
写一个数据结构,需要支持三种操作:
1.单点修改一个字符
2.单点插入一个字符
3.询问两个后缀的LCQ
思考过程:
一开始想到的是后缀数组,但是后缀数组似乎不支持插入的操作。那么能够在小于log的时间内求出LCQ的,也只有hash的
O(1)
O
(
1
)
了。而题目又需要提出一段区间来进行操作,所以很容易想到splay。没错,hash+splay就能够完美地解决这道题了。(最近做了好多hash+splay的题。。。)
具体做法:
数据结构题请看代码。
代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1.5e5+1000,mod=9875321;
int fa[maxn],c[maxn][2],size[maxn],v[maxn],h[maxn],p[maxn],id[maxn];
char ch[maxn];
int root,m,sz,n;
void pushup(int k)
{
int l=c[k][0],r=c[k][1];
size[k]=size[l]+size[r]+1;
h[k]=h[l]+(long long)v[k]*p[size[l]]%mod+(long long)p[size[l]+1]*h[r]%mod;
h[k]%=mod;
}
void rotate(int x)
{
int y=fa[x],z=fa[y],k=c[y][1]==x,w=c[x][!k];
c[z][c[z][1]==y]=x,c[y][k]=w,c[x][!k]=y;
fa[w]=y,fa[y]=x,fa[x]=z;
pushup(y);pushup(x);
}
void splay(int x,int tar)
{
while(fa[x]!=tar)
{
int y=fa[x],z=fa[y];
if(z!=tar) rotate((c[y][1]==x)^(c[z][1]==y)?x:y);
rotate(x);
}
if(tar==0) root=x;
}
void build(int l,int r,int f)
{
if(l>r) return;
int now=id[l],last=id[f];
if(l==r)
{
v[now]=h[now]=ch[l]-'a'+1;
fa[now]=last;size[now]=1;
if(l<f) c[last][0]=now;
else c[last][1]=now;
return;
}
int mid=(l+r)>>1;now=id[mid];
build(l,mid-1,mid);build(mid+1,r,mid);
v[now]=ch[mid]-'a'+1;fa[now]=last;pushup(now);
if(mid<f) c[last][0]=now;
else c[last][1]=now;
}
int find(int x)
{
int now=root;
while(1)
{
if(x<=size[c[now][0]]) now=c[now][0];
else if(x==size[c[now][0]]+1) return now;
else { x-=size[c[now][0]]+1;now=c[now][1]; }
}
}
int query(int k,int val)
{
int x=find(k);int y=find(k+val+1);
splay(x,0);splay(y,root);
int z=c[y][0];
return h[z];
}
int solve(int x,int y)
{
int l=1,r=min(sz-x,sz-y)-1,ans=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(query(x,mid)==query(y,mid)) l=mid+1,ans=mid;
else r=mid-1;
}
return ans;
}
void insert(int k,int val)
{
int x=find(k+1);int y=find(k+2);
splay(x,0);splay(y,root);
int z=++sz;c[y][0]=z,fa[z]=y,v[z]=val;
pushup(z);pushup(y);pushup(x);
}
int main()
{
scanf("%s",ch+2);
n=strlen(ch+2);
p[0]=1; for(int i=1;i<maxn;i++) p[i]=p[i-1]*27%mod;
for(int i=1;i<=n+2;i++) id[i]=i;
build(1,n+2,0);
sz=n+2;root=(n+3)>>1;
scanf("%d",&m);
int x,y;
char s[10],d[10];
while(m--)
{
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d",&x,&y);
printf("%d\n",solve(x,y));
}
else if(s[0]=='R')
{
scanf("%d",&x);
scanf("%s",d);
x=find(x+1);
splay(x,0);
v[root]=d[0]-'a'+1;
pushup(root);
}
else
{
scanf("%d",&x);
scanf("%s",d);
insert(x,d[0]-'a'+1);
}
}
return 0;
}