bzoj 1014:[JSOI2008]火星人prefix splay维护hash 二分求lcp

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define N 220000
int ch[N][2],pre[N],s[N],val[N],b[N],root,tot,siz[N];
char a[N];
int ff[N];
void up(int x){
    siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    s[x]=(s[ch[x][0]]*27+val[x])*ff[siz[ch[x][1]]]+s[ch[x][1]];
}
void rot(int x){
   int y=pre[x],z=pre[y],k=ch[y][0]==x;
   pre[ch[y][!k]=ch[x][k]]=y;
   pre[ch[x][k]=y]=x;
   pre[x]=z;
   if(z)ch[z][ch[z][1]==y]=x;
   else root=x;
   up(y);    
}
void splay(int x,int f){
    int y,z;
    for(;pre[x]!=f;){
       y=pre[x],z=pre[y];
       if(z==f)rot(x);
       else if((ch[y][1]==x)==(ch[z][1]==y))rot(y),rot(x);
       else rot(x),rot(x);    
    }
    up(x);
}
void select(int k,int f){
    int x=root;
    while(siz[ch[x][0]]+1!=k){
        if(siz[ch[x][0]]>=k)x=ch[x][0];
        else k-=siz[ch[x][0]]+1,x=ch[x][1];
    }
    splay(x,f);
}
int build(int l,int r,int p){
    if(l>r)return 0;
    int k=++tot;
    int mid=(l+r)>>1;
     pre[k]=p;
     val[k]=b[mid];    
     ch[k][0]=build(l,mid-1,k);
     ch[k][1]=build(mid+1,r,k);
     up(k);
     return k;
}
void add(int x,int y){
       select(x+1,0);
       select(x+2,root);
       ch[ch[root][1]][0]=++tot;
       siz[tot]=1;
       pre[tot]=ch[root][1];
       val[tot]=s[tot]=y;
       splay(tot,0);
}
void change(int x,int y){
   select(x,0);
   select(x+2,root);
   int k=ch[ch[root][1]][0];
   s[k]=val[k]=y;
   splay(k,0);    
}
bool deng(int x,int y,int k){
    select(x,0);
    select(x+k+1,root);
    int a1,a2;
    a1=s[ch[ch[root][1]][0]];
    select(y,0);
    select(y+k+1,root);
    a2=s[ch[ch[root][1]][0]];    
    return a1==a2;
}
int lcp(int x,int y){
    int le=0;
    int ri=min(tot-x,tot-y),mid;
    while(le+1!=ri){
       mid=(le+ri)>>1;
       if(deng(x,y,mid))le=mid;
       else ri=mid;    
    }
    return le;
}
int main(){
    ff[0]=1;
    for(int i=1;i<=100100;i++)ff[i]=ff[i-1]*27;
    scanf("%s",a);
    int t=strlen(a);
    for(int i=0;i<t;i++)b[i+1]=a[i]-'a'+1;
    int m;
    tot=2;
    root=1;
    ch[1][1]=2;
    pre[2]=1;
    ch[2][0]=build(1,t,2);
    up(2);
    up(1);
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
           char a,b;
           int c,d;
           scanf(" %c",&a);
        if(a=='Q'){
            scanf("%d%d",&c,&d);
            printf("%d\n",lcp(c,d));    
        }
        if(a=='I'){
           scanf("%d %c",&c,&b);
           add(c,b-'a'+1);    
        }
        if(a=='R'){
           scanf("%d %c",&c,&b);
           change(c,b-'a'+1);    
        }
        
    }
}

 

posted @ 2014-06-20 22:51  wangyucheng  阅读(141)  评论(0编辑  收藏  举报