题意
给出初始的字符串。需要进行M次操作描,操作有3种:
1.询问LCQ(x,y)。2.修改单个字符。3.插入单个字符。
其中LCQ(x,y)表示字符串x~len与y~len的最长公共前缀的长度。(len为当前串长)
M<=10^5
题解
对于静态的LCQ问题,我们可以对所有后缀排个序搞一搞实现,但是有了修改操作后就不行了,要另想办法。发现字符串的变化很自由,非常难控制,所以只好上大数据结构了,我们用splay维护序列,能解决修改问题。
但是询问操作如何实现呢?
splay并不能维护一些特别的信息,感觉很难办。注意到答案有二分性,是否能每次二分答案呢?要实现二分,需要快速比较两个长度相同的字符串是否相同。其实哈希一下就行了,实际效果是可以信赖的。哈希的值我们在splay中就可以维护了。
时间复杂度:O(nlog2n)
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL MOD=1000000007;
LL p[100005];
struct node{
LL key,size,val;
node *ch[2];
void maintain(){
size=ch[0]->size+ch[1]->size+1;
val=(p[ch[1]->size+1]*ch[0]->val+key*p[ch[1]->size]+ch[1]->val)%MOD;
}
int cmp(int &k){
if(k<=ch[0]->size) return 0;
if(k>ch[0]->size+1){ k-=ch[0]->size+1; return 1;}
return -1;
}
} nil,base[200005],*null=&nil,*root,*t_len;
typedef node* P_node;
void Splay_init(){ null->size=null->val=0; null->ch[0]=null->ch[1]=null; t_len=base; }
void rot(P_node &p,int d){
P_node k=p->ch[d^1]; p->ch[d^1]=k->ch[d]; k->ch[d]=p;
p->maintain(); k->maintain(); p=k;
}
void splay(P_node &p,int k){
int d1=p->cmp(k);
if(d1!=-1){
P_node p2=p->ch[d1];
int d2=p2->cmp(k);
if(d2!=-1){
splay(p2->ch[d2],k);
if(d1==d2) rot(p,d1^1), rot(p,d1^1);
else rot(p->ch[d1],d2^1), rot(p,d1^1);
} else rot(p,d1^1);
}
}
P_node newnode(int tkey){
t_len->key=tkey; t_len->size=1; t_len->val=tkey;
t_len->ch[0]=t_len->ch[1]=null;
return t_len++;
}
char b[1000005];
P_node build(int L,int R){
if(L>R) return null;
int mid=(L+R)>>1;
P_node p=newnode(b[mid]);
p->ch[0]=build(L,mid-1); p->ch[1]=build(mid+1,R);
p->maintain();
return p;
}
P_node merge(P_node left,P_node right){
splay(left,left->size); left->ch[1]=right;
left->maintain(); return left;
}
void split(P_node p,int k,P_node &left,P_node &right){
splay(p,k); left=p;
right=p->ch[1]; p->ch[1]=null;
left->maintain();
}
bool check(int x,int y,int now){
P_node left,right;
split(root,x-1,left,right); splay(right,now+1);
int t1=right->ch[0]->val;
root=merge(left,right);
split(root,y-1,left,right); splay(right,now+1);
int t2=right->ch[0]->val;
root=merge(left,right);
return t1==t2;
}
int Q;
int main(){
freopen("bzoj1014.in","r",stdin);
freopen("bzoj1014.out","w",stdout);
Splay_init();
p[0]=1; for(int i=1;i<=100000;i++) p[i]=(p[i-1]*13)%MOD;
scanf("%s",b+1); int len=strlen(b+1);
b[0]='['; b[len+1]=']';
root=build(0,len+1);
scanf("%d",&Q);
while(Q--){
char ch[5]; scanf("%s",ch);
if(ch[0]=='Q'){
int x,y; scanf("%d%d",&x,&y); x++; y++;
int L=1,R=min(root->size-x,root->size-y),res=0;
while(L<=R){
int mid=(L+R)>>1;
if(check(x,y,mid)) L=mid+1,res=mid;
else R=mid-1;
}
printf("%d\n",res);
}
if(ch[0]=='I'){
int x; scanf("%d",&x); x++; getchar();char ch=getchar();
P_node Left,Right; split(root,x,Left,Right);
splay(Right,1); Right->ch[0]=newnode(ch); Right->maintain();
root=merge(Left,Right);
}
if(ch[0]=='R'){
int x; scanf("%d",&x); x++; getchar();char ch=getchar();
P_node Left,Right; split(root,x,Left,Right);
splay(Left,Left->size-1); Left->ch[1]=newnode(ch); Left->maintain();
root=merge(Left,Right);
}
}
}