题目大意:维护一个字符串,支持插入字符和替换字符的操作,以及查询该字符串两个后缀的最长公共前缀长度
乍一看以为是后缀数组,然而并没有可持久化后缀数组(雾)
看题解才知道这是一道splay题,首先要对splay维护区间信息有一定了解
splay维护,插入字符,替换字符
而它的字树内所有儿子的中序遍历的hash值也可以通过splay维护
(这个推导式似乎烂大街了)
而后缀就是把i-1拎到根节点,然后把n+1拎到根节点的右儿子上,它的左儿子表示的就是hash值
至于如何查公共前缀呢?二分答案啊!询问的总时间是
这个二分答案的check函数 的满足条件并非常规的>=或者<=,而是==,所以为了防止正确答案被略掉,每次二分的过程中都记录一次mid作为答案,而加下来mid在查询范围内已经没有意义了,所以是r=mid-1而不是r=mid
我一开始插入打错了竟然还有80分,数据太水了hhhhh
?1 #include <cstdio> ?2 #include <cstring> ?3 #include <algorithm> ?4 #define il inline ?5 #define ui unsigned int ???6 #define ull unsigned long long ??7 #define seed 13131 ?8 #define N 110000 ?9 #define root d[0].ch[1] 10 using namespace std; 11 ?12 char str[N],Q[10],q[10]; 13 ull pw[N]; 14 int n,m,tot; 15 struct SPLAY{int fa,ch[2],sz;ull hsh,val;}d[N]; 16 int gc() 17 { 18 ????int rett=0,fh=1;char p=getchar(); 19 ????while(p<‘0‘||p>‘9‘){if(p==‘-‘)fh=-1;p=getchar();} 20 ????while(p>=‘0‘&&p<=‘9‘){rett=(rett<<3)+(rett<<1)+p-‘0‘;p=getchar();} 21 ????return rett*fh; 22 } 23 il ull idx(char c){return c-‘a‘+1;} 24 il void con(int x,int ff,int p){d[x].fa=ff,d[ff].ch[p]=x;} 25 il int idf(int x){return d[d[x].fa].ch[0]==x?0:1;} 26 il int cre(ull w){tot++;d[tot].val=w,d[tot].sz=1,d[tot].hsh=w;return tot;} 27 il void pushup(int x) 28 { 29 ????d[x].sz=d[d[x].ch[0]].sz+d[d[x].ch[1]].sz+1; 30 ????d[x].hsh=d[d[x].ch[0]].hsh*pw[d[d[x].ch[1]].sz+1]+(ull)d[x].val*pw[d[d[x].ch[1]].sz]+d[d[x].ch[1]].hsh; 31 } 32 il void rot(int x) 33 { 34 ????int y=d[x].fa;int ff=d[y].fa;int px=idf(x);int py=idf(y); 35 ????con(d[x].ch[px^1],y,px),con(y,x,px^1),con(x,ff,py); 36 ????pushup(y),pushup(x); 37 } 38 void splay(int x,int to) 39 { 40 ????to=d[to].fa; 41 ????while(d[x].fa!=to){ 42 ????????int y=d[x].fa; 43 ????????if(d[y].fa==to) rot(x); 44 ????????else if(idf(x)==idf(y)){rot(y);rot(x);} 45 ????????else{rot(x);rot(x);} 46 ????} 47 } 48 int build(int l,int r,int ff) 49 { 50 ????if(l>r) return 0; 51 ????int mid=(l+r)>>1; 52 ????int pos=cre(idx(str[mid])); 53 ????d[pos].fa=ff; 54 ????d[pos].ch[0]=build(l,mid-1,pos); 55 ????d[pos].ch[1]=build(mid+1,r,pos); 56 ????pushup(pos); 57 ????return pos; 58 } 59 int find_pos(int pos) 60 { 61 ????int x=root; 62 ????while(x) 63 ????{ 64 ????????if(d[d[x].ch[0]].sz>=pos) x=d[x].ch[0]; 65 ????????else{ 66 ????????????pos-=d[d[x].ch[0]].sz; 67 ????????????if(pos==1) return x; 68 ????????????pos--,x=d[x].ch[1]; 69 ????????} 70 ????} 71 ????return x; 72 } 73 void ins(int pos,ull w) 74 { 75 ????int ff=find_pos(pos+1),x,y;splay(ff,root); 76 ????if(!d[ff].ch[1]) ?77 ????????x=cre(w),con(x,ff,1),pushup(ff); 78 ????else{ 79 ????????x=d[ff].ch[1]; 80 ????????while(x) 81 ????????????if(d[x].ch[0]) x=d[x].ch[0]; 82 ????????????else break; 83 ????????y=cre(w),con(y,x,0),pushup(x); 84 ????????splay(x,root); 85 ????} 86 } 87 void replac(int pos,ull w) 88 { 89 ????int x=find_pos(pos+1);splay(x,root); 90 ????d[x].val=w;pushup(x); 91 } 92 il ull get_hsh(int pos) 93 { 94 ????int x=find_pos(pos); 95 ????splay(x,root); 96 ????int y=find_pos(n+2); 97 ????splay(y,d[x].ch[1]); 98 ????return d[d[d[x].ch[1]].ch[0]].hsh; 99 }100 il int check(int x,int y,int mid)101 {102 ????ull s1=0,s2=0,s3=0,s4=0;103 ????s1=get_hsh(x);104 ????if(x+mid<=n) s2=get_hsh(x+mid);105 ????s3=get_hsh(y);106 ????if(y+mid<=n) s4=get_hsh(y+mid);107 ????return (s1-s2==(s3-s4)*pw[y-x])?1:0;108 }109 int Query(int a,int b)110 {111 ????if(a>b){int t=a;a=b;b=t;}112 ????int l=1,r=n-b+1,ans=0;113 ????while(l<=r){114 ????????int mid=(l+r)>>1;115 ????????if(check(a,b,mid)) ans=mid,l=mid+1;116 ????????else r=mid-1;117 ????}118 ????return ans;119 }120 void stt()121 {122 ????n=strlen(str+1);pw[0]=1;123 ????for(int i=1;i<=100000;i++) pw[i]=pw[i-1]*seed;124 ????int x=cre(0),y=cre(0),z;125 ????con(x,0,1),con(y,1,1);126 ????z=build(1,n,y);127 ????con(z,y,0);128 ????pushup(y),pushup(x);129 }130 131 int main()132 {133 ????scanf("%s",str+1);134 ????stt();135 ????scanf("%d",&m);136 ????int x,y;137 ????for(int i=1;i<=m;i++)138 ????{139 ????????scanf("%s",Q);140 ????????if(Q[0]==‘Q‘){141 ????????????x=gc(),y=gc();142 ????????????printf("%d\n",Query(x,y));143 ????????}else if(Q[0]==‘I‘){144 ????????????x=gc();scanf("%s",q);145 ????????????ins(x,idx(q[0]));146 ????????????n++;147 ????????}else{148 ????????????x=gc();scanf("%s",q);149 ????????????replac(x,idx(q[0]));150 ????????}151 ????}152 ????return 0;153 }
bzoj 1014 [JSOI2008]火星人prefix (splay+二分答案+字符串hash)
原文地址:https://www.cnblogs.com/guapisolo/p/9697048.html