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
",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
",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;
}