bzoj1014: [JSOI2008]火星人prefix
题解:splay维护字符串hash,二分找lcp;
调试了约一天,错误原因是insert后n没有+1;
写完了这道题,加上前面两道平衡树题目,get新技能:[splay],[字符串hash];
这题有一个提速的关键:不要mod大素数,直接uLL自然溢出就好,提速很明显;
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<algorithm> #include<cstdlib> using namespace std; typedef unsigned long long LL; const int maxn=151000; int cnt=0,root=0,n,m; char s[maxn]; LL pre[maxn]; struct node{ int ch[2],siz,key,fa; LL hash; }e[maxn]; inline void updata(int x){ e[x].siz=e[e[x].ch[0]].siz+e[e[x].ch[1]].siz+1; e[x].hash=(e[e[x].ch[0]].hash+(LL)e[e[x].ch[1]].hash*pre[e[e[x].ch[0]].siz+1]+(LL)e[x].key*pre[e[e[x].ch[0]].siz]); } inline void rotate(int x,int d){ int y=e[x].fa; if(!y)return; e[x].fa=e[y].fa;e[y].fa=x;e[e[x].ch[d^1]].fa=y; e[y].ch[d]=e[x].ch[d^1];e[x].ch[d^1]=y; if(e[x].fa)e[e[x].fa].ch[e[e[x].fa].ch[1]==y]=x; updata(y);updata(x); } inline void splay(int x,int S){ if(!x)return; while(e[x].fa!=S){ if(e[e[x].fa].fa==S)rotate(x,e[e[x].fa].ch[1]==x); else { int y=e[x].fa;int z=e[y].fa; int d=(e[z].ch[1]==y); if(e[y].ch[d]==x){rotate(y,d);rotate(x,d);} else {rotate(x,d^1);rotate(x,d);} } } if(!S)root=x; } inline int build(int left,int right,int fa){ if(left>right)return 0; int mid=(left+right)>>1; int x=++cnt;e[x].siz=1;e[x].fa=fa; if(mid!=0&&mid!=n+1&&mid!=n+2)e[x].key=(s[mid]-'a'+1); e[x].ch[0]=build(left,mid-1,x); e[x].ch[1]=build(mid+1,right,x); updata(x); return x; } inline int find(int k){ int x=root; while(x){ if(e[e[x].ch[0]].siz+1==k)return x; if(k>e[e[x].ch[0]].siz+1)k-=(e[e[x].ch[0]].siz+1),x=e[x].ch[1]; else x=e[x].ch[0]; } if(x)splay(x,0); return x; } inline LL query(int x,int len){ int y=x+len+1; x=find(x);y=find(y); splay(x,0);splay(y,x); return e[e[y].ch[0]].hash; } int main(){ scanf("%s",s+1); n=strlen(s+1); pre[0]=1;for(int i=1;i<=150000;i++)pre[i]=(pre[i-1]*27); root=build(0,n+1,0); scanf("%d",&m); char ch;int x,y,k; while(m--){ scanf(" %c",&ch); if(ch=='Q'){ scanf("%d%d",&x,&y); if(x>y)swap(x,y); int left=0,right=n-y+1,ans=0; while(left<=right){ int mid=(left+right)>>1; if(query(x,mid)==query(y,mid))left=mid+1,ans=mid; else right=mid-1; } printf("%d\n",ans); continue; } if(ch=='R'){ scanf("%d %c",&x,&ch); x=find(x+1); splay(x,0); e[x].key=ch-'a'+1; updata(x); continue; } if(ch=='I'){ scanf("%d %c",&k,&ch);k++; x=find(k); splay(x,0); y=++cnt;n++; e[y].ch[1]=e[x].ch[1];e[y].fa=x;e[y].key=ch-'a'+1; e[e[x].ch[1]].fa=y;e[x].ch[1]=y; updata(y);updata(x); continue; } } return 0; }