[BZOJ1014][JSOI2008]火星人prefix
题意
给你一个串,支持三种操作:
1、在一个位置插入一个字符。
2、把一个位置的字符修改。
3、查询两个后缀的\(lcp\)。
任意时候字符串长度\(\le 10^5\),询问操作\(\le 10^4\),总操作数\(\le 1.5*10^5\)
sol
二分+\(hash\)。只要在\(splay\)上维护一个区间的\(hash\)值就可以了。
每次二分一个长度后直接把两个\(lcp\)对应的区间区间\(split\)出来然后判断。复杂度两个\(\log\)。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ull unsigned long long
int gi()
{
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 1e5+5;
const int base = 1705;
int n,m,fa[N],ch[2][N],key[N],sz[N],root;ull pw[N],hash[N];
char s[N];
bool son(int x){return x==ch[1][fa[x]];}
void pushup(int x)
{
hash[x]=hash[ch[0][x]]*pw[sz[ch[1][x]]+1]+key[x]*pw[sz[ch[1][x]]]+hash[ch[1][x]];
sz[x]=sz[ch[0][x]]+sz[ch[1][x]]+1;
}
void rotate(int x)
{
int y=fa[x],z=fa[y],c=son(x);
ch[c][y]=ch[c^1][x];if (ch[c][y]) fa[ch[c][y]]=y;
fa[x]=z;if (z) ch[son(y)][z]=x;
ch[c^1][x]=y;fa[y]=x;pushup(y);
}
void splay(int x,int goal)
{
for (int y=fa[x];y!=goal;rotate(x),y=fa[x])
if (fa[y]!=goal) son(x)^son(y)?rotate(x):rotate(y);
pushup(x);if (!goal) root=x;
}
int find(int k,int goal)
{
int x=root;
while (base){
if (k<=sz[ch[0][x]]) x=ch[0][x];
else if (k==sz[ch[0][x]]+1) {splay(x,goal);return x;}
else k-=sz[ch[0][x]]+1,x=ch[1][x];
}
}
int build(int l,int r,int ff)
{
if (l>r) return 0;
int mid=l+r>>1;
key[mid]=s[mid];fa[mid]=ff;
ch[0][mid]=build(l,mid-1,mid);
ch[1][mid]=build(mid+1,r,mid);
pushup(mid);return mid;
}
ull cal(int l,int r)
{
find(l,0);find(r+2,root);
return hash[ch[0][ch[1][root]]];
}
int main()
{
pw[0]=1;
for (int i=1;i<N;++i) pw[i]=pw[i-1]*base;
scanf("%s",s+2);n=strlen(s+2);
root=build(1,n+2,0);
m=gi();n+=2;
while (m--)
{
char opt=getchar();
while (opt!='Q'&&opt!='R'&&opt!='I') opt=getchar();
if (opt=='Q')
{
int x=gi(),y=gi();if (x>y) swap(x,y);
int l=1,r=n-y-1,ans=0;
while (l<=r)
{
int mid=l+r>>1;
if (cal(x,x+mid-1)==cal(y,y+mid-1)) ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
}
if (opt=='R')
{
int x=gi();x=find(x+1,0);
key[x]=getchar();pushup(x);
}
if (opt=='I')
{
int x=gi(),y=find(x+1,0),z=find(x+2,root);
key[++n]=getchar();ch[0][fa[n]=z]=n;
splay(n,0);
}
}
return 0;
}