bzoj1014: [JSOI2008]火星人prefix

题解:splay维护字符串hash,二分找lcp;

调试了约一天,错误原因是insert后n没有+1;

写完了这道题,加上前面两道平衡树题目,get新技能:[splay],[字符串hash];

这题有一个提速的关键:不要mod大素数,直接uLL自然溢出就好,提速很明显;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cstdlib>
using namespace std;
typedef unsigned long long LL; 
const int maxn=151000;
int cnt=0,root=0,n,m;
char s[maxn];
LL pre[maxn];
struct node{
    int ch[2],siz,key,fa;
    LL hash;
}e[maxn];
inline void updata(int x){
    e[x].siz=e[e[x].ch[0]].siz+e[e[x].ch[1]].siz+1;
    e[x].hash=(e[e[x].ch[0]].hash+(LL)e[e[x].ch[1]].hash*pre[e[e[x].ch[0]].siz+1]+(LL)e[x].key*pre[e[e[x].ch[0]].siz]);
}
inline void rotate(int x,int d){
    int y=e[x].fa;
    if(!y)return;
    e[x].fa=e[y].fa;e[y].fa=x;e[e[x].ch[d^1]].fa=y;
    e[y].ch[d]=e[x].ch[d^1];e[x].ch[d^1]=y;
    if(e[x].fa)e[e[x].fa].ch[e[e[x].fa].ch[1]==y]=x;
    updata(y);updata(x);
}
inline void splay(int x,int S){
    if(!x)return;
    while(e[x].fa!=S){
        if(e[e[x].fa].fa==S)rotate(x,e[e[x].fa].ch[1]==x);
        else {
            int y=e[x].fa;int z=e[y].fa;
            int d=(e[z].ch[1]==y);
            if(e[y].ch[d]==x){rotate(y,d);rotate(x,d);}
            else {rotate(x,d^1);rotate(x,d);}
        }
    }
    if(!S)root=x;
}
inline int build(int left,int right,int fa){
    if(left>right)return 0;
    int mid=(left+right)>>1;
    int x=++cnt;e[x].siz=1;e[x].fa=fa;
    if(mid!=0&&mid!=n+1&&mid!=n+2)e[x].key=(s[mid]-'a'+1);
    e[x].ch[0]=build(left,mid-1,x);
    e[x].ch[1]=build(mid+1,right,x);
    updata(x);
    return x;
}
inline int find(int k){
    int x=root;
    while(x){
        if(e[e[x].ch[0]].siz+1==k)return x;
        if(k>e[e[x].ch[0]].siz+1)k-=(e[e[x].ch[0]].siz+1),x=e[x].ch[1];
        else x=e[x].ch[0];
    }
    if(x)splay(x,0);
    return x;
}
inline LL query(int x,int len){
    int y=x+len+1;
    x=find(x);y=find(y);
    splay(x,0);splay(y,x);
    return e[e[y].ch[0]].hash;
}
int main(){
    scanf("%s",s+1);
    n=strlen(s+1);
    pre[0]=1;for(int i=1;i<=150000;i++)pre[i]=(pre[i-1]*27);
    root=build(0,n+1,0);
    scanf("%d",&m);
    char ch;int x,y,k;
    while(m--){
        scanf(" %c",&ch);
        if(ch=='Q'){
            scanf("%d%d",&x,&y);
            if(x>y)swap(x,y);
            int left=0,right=n-y+1,ans=0;
            while(left<=right){
                int mid=(left+right)>>1;
                if(query(x,mid)==query(y,mid))left=mid+1,ans=mid;
                else right=mid-1;
            }
            printf("%d\n",ans);
            continue;
        }
        if(ch=='R'){
            scanf("%d %c",&x,&ch);
            x=find(x+1);
            splay(x,0);
            e[x].key=ch-'a'+1;
            updata(x);
            continue;
        }
        if(ch=='I'){
            scanf("%d %c",&k,&ch);k++;
            x=find(k);
            splay(x,0);
            y=++cnt;n++;
            e[y].ch[1]=e[x].ch[1];e[y].fa=x;e[y].key=ch-'a'+1;
            e[e[x].ch[1]].fa=y;e[x].ch[1]=y;
            updata(y);updata(x);
            continue;
        }
    }
    return 0;
}

 

posted @ 2016-09-29 14:03  CHADLZX  阅读(188)  评论(0编辑  收藏  举报