bzoj1014: [JSOI2008]火星人prefix
我TM的怕不是个傻逼。。check里面比较hash搞成比较c,居然还能过数据,还过了n个对拍。。果然假如考试信样例就有鬼了。
嗯隔壁哈老师告诉我,hash其实不用mod,直接自然溢出就行,get到新姿势。
这道题前两个操作明显可以用伸展树来解决,问题在于比较两个后缀的前缀,那我们的做法就是令伸展树记录一个h表示当前子树的hash,那我们通过比较hash就可以方便的知道,两个子串是否相等,那比较后缀时,就用二分枚举匹配长度,然后比较hash就行了、
#include<cstdio> #include<cstring> using namespace std; int mi[110000]; struct node { int f,c,h,hash,son[2];//hash表示以当前节点管理的节点的hash值 }tr[110000];int root,len; void update(int x) { int lc=tr[x].son[0],rc=tr[x].son[1]; tr[x].c=tr[lc].c+tr[rc].c+1; tr[x].hash=tr[lc].hash*mi[tr[rc].c+1] + tr[x].h*mi[tr[rc].c] + tr[rc].hash; } void rotate(int x,int w) { int f=tr[x].f,ff=tr[f].f; int r,R; r=tr[x].son[w];R=f; tr[R].son[1-w]=r; if(r!=0)tr[r].f=R; r=x;R=ff; if(tr[ff].son[0]==f)tr[R].son[0]=r; else tr[R].son[1]=r; tr[r].f=R; r=f;R=x; tr[R].son[w]=r; tr[r].f=R; update(f); update(x); } void splay(int x,int rt) { while(tr[x].f!=rt) { int f=tr[x].f,ff=tr[f].f; if(ff==rt) { if(x==tr[f].son[0])rotate(x,1); else rotate(x,0); } else { if(tr[f].son[0]==x&&tr[ff].son[0]==f){rotate(f,1);rotate(x,1);} else if(tr[f].son[1]==x&&tr[ff].son[0]==f){rotate(x,0);rotate(x,1);} else if(tr[f].son[0]==x&&tr[ff].son[1]==f){rotate(x,1);rotate(x,0);} else if(tr[f].son[1]==x&&tr[ff].son[1]==f){rotate(f,0);rotate(x,0);} } } if(rt==0)root=x; } void ins(int h,int f) { len++; tr[len].c=1;tr[len].h=h; tr[len].hash=h; tr[len].son[0]=tr[len].son[1]=0; if(f==0){tr[len].f=0;root=len;} else { splay(f,0); if(tr[f].son[1]==0) { tr[len].f=f; tr[f].son[1]=len; } else { f=tr[f].son[1]; while(tr[f].son[0]!=0)f=tr[f].son[0]; tr[len].f=f; tr[f].son[0]=len; } splay(f,0); } } int findweizhi(int k) { int x=root; while(x!=0) { int d=tr[tr[x].son[0]].c+1; if(k<d) x=tr[x].son[0]; else if(d<k){x=tr[x].son[1];k-=d;} else break; } return x; } void change(int x,int h) { splay(x,0); tr[x].h=h; update(x); } bool check(int x,int y,int mid) { int xl=findweizhi(x),xr=findweizhi(x+mid-1); int yl=findweizhi(y),yr=findweizhi(y+mid-1); if(tr[xl].h!=tr[yl].h||tr[xr].h!=tr[yr].h)return false; if(mid<=2)return true; int hx,hy; splay(xl,0);splay(xr,xl); hx=tr[tr[xr].son[0]].hash; splay(yl,0);splay(yr,yl); hy=tr[tr[yr].son[0]].hash; if(hx==hy)return true; return false; } char ss[110000]; int main() { freopen("hehe.in","r",stdin); freopen("w.out","w",stdout); mi[0]=1;for(int i=1;i<=100000;i++)mi[i]=mi[i-1]*27; root=len=0;ins(0,0); scanf("%s",ss+1);int slen=strlen(ss+1); for(int i=1;i<=slen;i++)ins(int(ss[i]-'a'+1),len); int m,x,y; scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%s",ss+1); if(ss[1]=='R') { scanf("%d%s",&x,ss+1); x=findweizhi(x+1); change(x,int(ss[1]-'a'+1)); } else if(ss[1]=='I') { scanf("%d%s",&x,ss+1); x=findweizhi(x+1); ins(int(ss[1]-'a'+1),x); } else { scanf("%d%d",&x,&y);x++;y++; if(x>y){int t=x;x=y;y=t;} int l=1,r=len-y+1,ans=0; while(l<=r) { int mid=(l+r)/2; if(check(x,y,mid)==true) { l=mid+1; ans=mid; } else r=mid-1; } printf("%d\n",ans); } } return 0; }
pain and happy in the cruel world.