【数据结构】【Splay】BZOJ1014&JSOI2008 火星人prefix

题意:

动态维护两后缀的最长公共前缀,要支持单点修改,单点插入。


分析:

本来以为要用什么后缀数据结构。。。结果想了半天无果。

才发现这题可以直接字符串hash+Splay水过。。。

真是傻了。。。Splay具体操作就是一般的序列Splay。。。每个点维护一个hash值表示它的子树的hash值。


#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
typedef unsigned long long ull;
ull fsp[MAXN];
int cnt;
struct node *NIL;
struct node{
    node *ch[2],*fa;
    ull hash,val;
    int siz;
    bool Dir(){
        return this==fa->ch[1];
    }
    void Setchild(node *x,int d){
        ch[d]=x;
        if(x!=NIL)
            x->fa=this; 
    }
    void pushup(){
        siz=ch[0]->siz+ch[1]->siz+1;
        hash=ch[0]->hash+val*fsp[ch[0]->siz]+ch[1]->hash*fsp[ch[0]->siz+1];
    }
}tree[MAXN],*root,*ncnt;
node * Newnode(ull val){
    node *p=++ncnt;
    p->hash=val;
    p->siz=1;
    p->val=val;
    p->ch[0]=p->ch[1]=p->fa=NIL;
    return p;
}
void Rotate(node *x){
    int d=x->Dir();
    node *y=x->fa;
    if(y==root){
        root=x;
        x->fa=NIL;  
    }
    else
        y->fa->Setchild(x,y->Dir());
    y->Setchild(x->ch[!d],d);
    x->Setchild(y,!d);
    y->pushup();
}
void Splay(node *x,node *rt){
    //x->pushdown();
    while(x->fa!=rt){
        node *y=x->fa;
        if(y->fa==rt)
            Rotate(x);
        else{
            if(x->Dir()==y->Dir())
                Rotate(y);
            else
                Rotate(x);
            Rotate(x);
        }
    }
    x->pushup();
}
node *find_val(node *x,int val){
    if(x->ch[0]->siz>=val)
        return find_val(x->ch[0],val);
    val-=x->ch[0]->siz;
    if(val==1)
        return x;
    return find_val(x->ch[1],val-1);
}
node* find_nxt(node *x,int d){
    while(x->ch[d]!=NIL)
        x=x->ch[d];
    return x;
}
void Ins(int pos,int val){
    node *x=find_val(root,pos+1);
    Splay(x,NIL);
    node *y=find_nxt(x->ch[1],0);
    if(y==NIL){
        x->Setchild(Newnode(val),1);    
        return ;
    }
    Splay(y,x);
    node *z=Newnode(val);
    z->Setchild(x->ch[1],1);
    x->Setchild(z,1);
    z->pushup();
    x->pushup();
}
void Change(int pos,int val){
    node *x=find_val(root,pos+1);
    Splay(x,NIL);
    x->val=val;
    x->pushup();
}
bool check(int len,int pl,int pr){
    node *x,*y;
    ull hash1,hash2;
    x=find_val(root,pl);
    Splay(x,NIL);
    y=find_val(x->ch[1],len+1);
    Splay(y,x);
    hash1=y->ch[0]->hash;
    //PF("[%d %llu ",len,hash1);

    x=find_val(root,pr);
    Splay(x,NIL);
    y=find_val(x->ch[1],len+1);
    Splay(y,x);
    hash2=y->ch[0]->hash;
    //PF("%llu]\n",hash2);

    return hash1==hash2;
}
int Que(int pl,int pr){
    int l=1,r=cnt-pr+1;
    int ans=0;
    while(l<=r){
        //PF("{%d %d}\n",l,r);
        int mid=(l+r)>>1;
        if(check(mid,pl,pr)==1){
            ans=mid;
            l=mid+1;
        }
        else
            r=mid-1;
    }
    return ans;
}

char s[MAXN];
node* build(int l,int r){
    if(l==r){
        node *x=Newnode(s[l]-'a'+1);
        return x;
    }
    int mid=(l+r)>>1;
    node *x=Newnode(s[mid]-'a'+1);
    if(l<mid)
        x->Setchild(build(l,mid-1),0);
    if(mid<r)
        x->Setchild(build(mid+1,r),1);
    x->pushup();
    return x;
}
void init(){
    NIL=&tree[0];
    NIL->ch[0]=NIL->ch[1]=NIL->fa=NIL;
    ncnt=&tree[0];  
}
void Debug(node *x){
    if(x==NIL)
        return ;
    Debug(x->ch[0]);
    PF("%c",x->val-1+'a');
    Debug(x->ch[1]);
}
int main(){
    init();
    fsp[0]=1;
    for(int i=1;i<=100000;i++)
        fsp[i]=fsp[i-1]*131ull;
    SF("%s",s+2);
    int n=strlen(s+2);
    cnt=n;
    s[1]='a';
    s[n+2]='a';
    root=build(1,n+2);
    //Debug(root);
    int q,u,v;
    SF("%d",&q);
    while(q--){
        SF("%s",s);
        if(s[0]=='Q'){
            SF("%d%d",&u,&v);
            if(u>v)
                swap(u,v);
            PF("%d\n",Que(u,v));
        }
        else if(s[0]=='R'){
            SF("%d",&u);
            SF("%s",s);
            Change(u,s[0]-'a'+1);
        }
        else{
            cnt++;
            SF("%d",&u);
            SF("%s",s);
            Ins(u,s[0]-'a'+1);
        }
        //Debug(root);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_34454069/article/details/81266534
今日推荐