bzoj1014 [JSOI2008]火星人prefix

bzoj1014 [JSOI2008]火星人prefix


原题链接


题解

平衡树维护字符串。
至于LCP二分+哈希
\(hash[i]=hash[ls]+ch×base^{ls->size}+hash[rs]×base^{ls->size+1}\)


Code

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cstring>
#define Fname "bzoj_1014"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
#define fir first
#define sec second
#define pr pair<point,point>
#define mp make_pair
typedef unsigned int ll;
il int gi(){
    rg int x=0;rg char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x;
}
typedef struct node* point;
point null;
int seed=2333;
il int Rand(){return seed=seed*19260817ll%2147483647;}
const int maxn=1e5+2;
ll base[maxn],Base[maxn];
struct node{
    int size,rand,ch;
    ll h,H;
    point ls,rs;
    node(char _ch){
	ch=_ch-'`',rand=Rand(),size=1,ls=rs=null;
	h=H=ch;
    }
    il vd reset(){
	size=ls->size+rs->size+1;
	h=ls->h+base[ls->size]*ch+base[ls->size+1]*rs->h;
	H=ls->H+Base[ls->size]*ch+Base[ls->size+1]*rs->H;
    }
};
point root;
il point build(){
    char str[100010];
    scanf("%s",str+1);
    int n=strlen(str+1);
    point now,stk[n+2],lst;int top=0;
    rep(i,1,n){
	now=new node(str[i]),lst=null;
	while(top&&stk[top]->rand>now->rand)lst=stk[top],stk[top--]->reset();
	if(top)stk[top]->rs=now;
	now->ls=lst,stk[++top]=now;
    }
    while(top)stk[top--]->reset();
    return stk[1];
}
il point merge(point a,point b){
    if(a==null){b->reset();return b;}
    if(b==null){a->reset();return a;}
    if(a->rand<b->rand){a->rs=merge(a->rs,b);a->reset();return a;}
    else{b->ls=merge(a,b->ls);b->reset();return b;}
}
il pr split(point now,int num){
    if(now==null)return mp(null,null);
    point ls=now->ls,rs=now->rs;
    if(num==now->ls->size){now->ls=null,now->reset();return mp(ls,now);}
    if(num==now->ls->size+1){now->rs=null,now->reset();return mp(now,rs);}
    if(now->ls->size>num){
	pr T=split(now->ls,num);
	now->ls=T.sec,now->reset();
	return mp(T.fir,now);
    }else{
	pr T=split(now->rs,num-now->ls->size-1);
	now->rs=T.fir,now->reset();
	return mp(now,T.sec);
    }
}
il vd Get(char&ch){do ch=getchar();while(ch<'a'||ch>'z');}
il vd change(){
    int k=gi();char ch;Get(ch);
    pr T=split(root,k-1),TT=split(T.sec,1);
    TT.fir->ch=TT.fir->h=TT.fir->H=ch-'`';
    root=merge(T.fir,merge(TT.fir,TT.sec));
}
il vd ins(){
    int k=gi();char ch;Get(ch);
    pr T=split(root,k);
    root=merge(T.fir,merge(new node(ch),T.sec));
}
il pair<ll,ll>GetHash(int l,int r){
    pair<ll,ll>ret;
    pr T=split(root,l-1),TT=split(T.sec,r-l+1);
    ret=mp(TT.fir->h,TT.fir->H);
    root=merge(T.fir,merge(TT.fir,TT.sec));
    return ret;
}
il bool check(int&x,int&y,int mid){
    pair<ll,ll>a=GetHash(x,x+mid-1),b=GetHash(y,y+mid-1);
    return a.fir==b.fir&&a.sec==b.sec;
}
il vd solve(){
    int x=gi(),y=gi();
    int mid,l=0,r=min(root->size-x+1,root->size-y+1);
    while(l<r){
	mid=(l+r)>>1;
	if(check(x,y,mid+1))l=mid+1;
	else r=mid;
    }printf("%d\n",l);
}
int main(){
    freopen(Fname".in","r",stdin);
    freopen(Fname".out","w",stdout);
    null=new node('`');
    null->size=0;
    null->ls=null->rs=null;
    base[0]=1;
    rep(i,1,1e5)base[i]=base[i-1]*29;
    Base[0]=1;
    rep(i,1,1e5)Base[i]=Base[i-1]*23333;
    root=build();
    int m=gi();char opt;
    while(m--){
	do opt=getchar();while(opt<'A'||opt>'Z');
	if(opt=='Q')solve();
	else if(opt=='R')change();
	else ins();
    }
    return 0;
}

一个hash快些

// It is made by XZZ
#include<cstdio>
#include<algorithm>
#include<cstring>
#define Fname "bzoj_1014"
using namespace std;
#define rep(a,b,c) for(rg int a=b;a<=c;a++)
#define drep(a,b,c) for(rg int a=b;a>=c;a--)
#define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
#define il inline
#define rg register
#define vd void
#define fir first
#define sec second
#define pr pair<point,point>
#define mp make_pair
typedef unsigned int ll;
il int gi(){
    rg int x=0;rg char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x;
}
typedef struct node* point;
point null;
int seed=2333;
il int Rand(){return seed=seed*19260817ll%2147483647;}
const int maxn=1e5+2;
ll base[maxn];
struct node{
    int size,rand,ch;
    ll h;
    point ls,rs;
    node(char _ch){
	ch=_ch-'`',rand=Rand(),size=1,ls=rs=null;
	h=ch;
    }
    il vd reset(){
	size=ls->size+rs->size+1;
	h=ls->h+base[ls->size]*ch+base[ls->size+1]*rs->h;
    }
};
point root;
il point build(){
    char str[100010];
    scanf("%s",str+1);
    int n=strlen(str+1);
    point now,stk[n+2],lst;int top=0;
    rep(i,1,n){
	now=new node(str[i]),lst=null;
	while(top&&stk[top]->rand>now->rand)lst=stk[top],stk[top--]->reset();
	if(top)stk[top]->rs=now;
	now->ls=lst,stk[++top]=now;
    }
    while(top)stk[top--]->reset();
    return stk[1];
}
il point merge(point a,point b){
    if(a==null){b->reset();return b;}
    if(b==null){a->reset();return a;}
    if(a->rand<b->rand){a->rs=merge(a->rs,b);a->reset();return a;}
    else{b->ls=merge(a,b->ls);b->reset();return b;}
}
il pr split(point now,int num){
    if(now==null)return mp(null,null);
    point ls=now->ls,rs=now->rs;
    if(num==now->ls->size){now->ls=null,now->reset();return mp(ls,now);}
    if(num==now->ls->size+1){now->rs=null,now->reset();return mp(now,rs);}
    if(now->ls->size>num){
	pr T=split(now->ls,num);
	now->ls=T.sec,now->reset();
	return mp(T.fir,now);
    }else{
	pr T=split(now->rs,num-now->ls->size-1);
	now->rs=T.fir,now->reset();
	return mp(now,T.sec);
    }
}
il vd Get(char&ch){do ch=getchar();while(ch<'a'||ch>'z');}
il vd change(){
    int k=gi();char ch;Get(ch);
    pr T=split(root,k-1),TT=split(T.sec,1);
    TT.fir->ch=TT.fir->h=ch-'`';
    root=merge(T.fir,merge(TT.fir,TT.sec));
}
il vd ins(){
    int k=gi();char ch;Get(ch);
    pr T=split(root,k);
    root=merge(T.fir,merge(new node(ch),T.sec));
}
il ll GetHash(int l,int r){
    ll ret;
    pr T=split(root,l-1),TT=split(T.sec,r-l+1);
    ret=TT.fir->h;
    root=merge(T.fir,merge(TT.fir,TT.sec));
    return ret;
}
il bool check(int&x,int&y,int mid){
    ll a=GetHash(x,x+mid-1),b=GetHash(y,y+mid-1);
    return a==b;
}
il vd solve(){
    int x=gi(),y=gi();
    int mid,l=0,r=min(root->size-x+1,root->size-y+1);
    while(l<r){
	mid=(l+r)>>1;
	if(check(x,y,mid+1))l=mid+1;
	else r=mid;
    }printf("%d\n",l);
}
int main(){
    freopen(Fname".in","r",stdin);
    freopen(Fname".out","w",stdout);
    null=new node('`');
    null->size=0;
    null->ls=null->rs=null;
    base[0]=1;
    rep(i,1,1e5)base[i]=base[i-1]*29;
    root=build();
    int m=gi();char opt;
    while(m--){
	do opt=getchar();while(opt<'A'||opt>'Z');
	if(opt=='Q')solve();
	else if(opt=='R')change();
	else ins();
    }
    return 0;
}
posted @ 2017-09-07 13:47  菜狗xzz  阅读(308)  评论(0编辑  收藏  举报