正题
题目链接:https://www.luogu.com.cn/problem/P4036
题目大意
一个字符串要求支持
- 插入一个字符
- 修改一个字符
- 询问两个后缀的最长公共前缀。
解题思路
如果不考虑修改我们可以用二分+hash+hash+hash解决该问题,但是涉及到修改和插入我们考虑用SplaySplaySplay维护hashhashhash值。
合并时使用hash=hashl∗psizr+1+val∗psizr+hashrhash=hash_l*p^{siz_r+1}+val*p^{siz_r}+hash_rhash=hashl∗psizr+1+val∗psizr+hashr进行合并即可。
codecodecode
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ull unsigned long long
using namespace std;
const int N=2e5+10;
const ull base=131;
struct node{int siz;ull val,hash;
}a[N];
int n,root,tot,m;
int t[N][2],fa[N];
char s[N];
ull p[N];
bool Direct(int x)
{return t[fa[x]][1]==x;}
void Merge(int x){a[x].siz=a[t[x][0]].siz+a[t[x][1]].siz+1;a[x].hash=p[a[t[x][1]].siz+1]*a[t[x][0]].hash+p[a[t[x][1]].siz]*a[x].val+a[t[x][1]].hash;
}
void Connect(int x,int y,int dir)
{t[x][dir]=y;fa[y]=x;}
void Rotate(int x){int y=fa[x],root=fa[fa[x]];int ys=Direct(x),rs=Direct(y);int z=t[x][ys^1];Connect(y,z,ys);Connect(x,y,ys^1);Connect(root,x,rs);Merge(y);Merge(x);return;
}
void Splay(int x,int f)
{while(fa[x]!=f){int up=fa[x];if(fa[up]==f) Rotate(x);else if(Direct(x)==Direct(up))Rotate(up),Rotate(x);else Rotate(x),Rotate(x); }return;
}
int Find(int x,int k)
{if(a[t[x][0]].siz>=k) return Find(t[x][0],k);if(a[t[x][0]].siz+1==k) return x;return Find(t[x][1],k-a[t[x][0]].siz-1);
}
int Split(int l,int r)
{int x=Find(root,l),y=Find(root,r+2);Splay(x,0);Splay(y,x);root=x;return t[y][0];
}
ull ValSeq(int x,int y)
{return a[Split(x,y)].hash;
}
int main()
{scanf("%s",s+1);n=strlen(s+1);a[1].siz=p[0]=1;for(int i=1;i<N;i++)p[i]=p[i-1]*base;for(int i=1;i<=n;i++){a[i+1].val=s[i]-'a'+1;fa[i]=i+1;t[i+1][0]=i;Merge(i+1);}fa[n+1]=n+2;t[n+2][0]=n+1;Merge(n+2);root=tot=n+2;scanf("%d",&m);while(m--){char op[2];scanf("%s",op);if(op[0]=='Q'){int x,y;scanf("%d%d",&x,&y);int l=0,r=min(n-x,n-y);while(l<=r){int mid=(l+r)/2;if(ValSeq(x,x+mid)==ValSeq(y,y+mid)) l=mid+1;else r=mid-1;}printf("%d\n",r+1);}if(op[0]=='R'){int x;char c[2];scanf("%d%s",&x,c);int k=Split(x,x);a[k].val=a[k].hash=c[0]-'a'+1;Splay(k,0);root=k;}if(op[0]=='I'){int x;char c[2];scanf("%d%s",&x,c);x++;int l=Find(root,x),r=Find(root,x+1);Splay(l,0);Splay(r,l);n++;fa[++tot]=r;t[r][0]=tot;a[tot].siz=1;a[tot].val=a[tot].hash=c[0]-'a'+1;Splay(tot,0);root=tot;}}
}