BZOJ1014: [JSOI2008]火星人prefix
Splay·HASH
题解:
一般这种又是插入又是修改的直接上splay啦~
splay维护HASH,求LCP的时候二分一下查HASH是否相等。
复杂度O(Qlog2n)
其实也可以写预先为将来所有可能的位置开点的线段树,原理差不多。
代码比较难写QWQ
肯定是我太弱了。。。
Code:
#include <iostream>
#include <cstring>
#include <cstdio>
#define D(x) cout<<#x<<" = "<<x<<" "
#define O(x) cout<<x<<" "
#define E cout<<endl
using namespace std;
typedef unsigned long long ull;
const int N = 100005;
const ull BASE = 1e9+7;
ull pow[N]; int n,m; char str[N];
struct Node{
Node *pa, *ch[2];
int sz, c; ull hash;
Node(){ pa=ch[0]=ch[1]=NULL; sz=1; c=0; hash=0; }
void update();
void setch(Node*,int);
int getwh();
} pool[N], *root, *lptr, *rptr;
int ptop=0;
void Node::update(){
sz=1; if(ch[0]!=NULL)sz+=ch[0]->sz; if(ch[1]!=NULL)sz+=ch[1]->sz;
hash=0; int lsz=0;
if(ch[0]!=NULL){ lsz=ch[0]->sz; hash+=ch[0]->hash; }
hash+=c*pow[lsz];
if(ch[1]!=NULL){ hash+=ch[1]->hash*pow[lsz+1]; }
}
void Node::setch(Node *child,int wh){
ch[wh]=child;
if(child!=NULL) child->pa=this;
update();
}
int Node::getwh(){
return pa->ch[0]==this ? 0 : 1;
}
void dfs(Node *x){
if(x==NULL) return;
dfs(x->ch[0]); O(x->c); dfs(x->ch[1]);
}
void dfs(){ puts("dfs:"); dfs(root); E; }
void rotate(Node *x){
Node *y=x->pa, *z=x->pa->pa; int wh=x->getwh();
y->setch(x->ch[wh^1],wh); x->setch(y,wh^1);
x->pa=z; if(z!=NULL) z->ch[z->ch[0]==y?0:1]=x;
}
void splay(Node *x,Node *tar){
if(x==tar) return;
for(; x->pa!=tar; rotate(x)) if(x->pa->pa!=tar)
x->getwh()==x->pa->getwh() ? rotate(x->pa) : rotate(x);
if(tar==NULL) root=x;
}
Node* find(int pos){
Node *now=root; int lsz=0;
while(now!=NULL){
int tp; if(now->ch[0]!=NULL)tp=now->ch[0]->sz+1; else tp=1;
if(lsz+tp < pos){ lsz+=tp; now=now->ch[1]; }
else if(lsz+tp > pos){ now=now->ch[0]; }
else{ return now; }
}
return NULL;
}
void insert(int pos,int c){
// puts("insert:"); D(pos); D(c); E;
Node *newone = &pool[ptop++]; newone->c=c;
Node *x=find(pos); Node *y=find(pos+1);
// D(x->c); D(y->c); E;
splay(x,NULL); splay(y,x); newone->setch(y,1); x->setch(newone,1);
}
void change(int pos,int c){
Node *x=find(pos);
x->c=c; splay(x,NULL);
}
ull getHash(int l,int r){
Node *x=find(l-1); Node *y=find(r+1);
splay(x,NULL); splay(y,x);
return y->ch[0]->hash;
}
int solve(int a,int b){
int l=0,r=n-(max(a,b)-1)+1,mid;
while(l<r){
mid=l+(r-l+1)/2;
if(getHash(a,a+mid-1) == getHash(b,b+mid-1)) l=mid;
else r=mid-1;
}
return l;
}
void init(){
pow[0]=1; for(int i=1;i<=100000;i++) pow[i]=pow[i-1]*BASE;
ptop=0;
lptr=&pool[ptop++]; lptr->c=-1; root=lptr;
rptr=&pool[ptop++]; rptr->c=-2; lptr->setch(rptr,1);
}
int main(){
freopen("a.in","r",stdin);
scanf("%s",str); n=strlen(str);
init();
for(int i=1;i<=n;i++) insert(i,str[i-1]-'a'+1);
// dfs();
scanf("%d",&m); int a,b; char op[5];
for(int i=1;i<=m;i++){
// D(i); E;
scanf("%s",op);
if(op[0]=='Q'){
scanf("%d%d",&a,&b); a++; b++;
printf("%d\n",solve(a,b));
}
else if(op[0]=='R'){
scanf("%d%s",&a,str); a++;
change(a,str[0]-'a'+1);
}
else if(op[0]=='I'){
scanf("%d%s",&a,str); a++; n++;
insert(a,str[0]-'a'+1);
}
}
}