动态询问LCP,所以我们不好用后缀数组
考虑使用维护序列问题的splay+hash求LCP
这里mark一下,hash求LCP常用mo=9875321
自然溢出的话交上去莫名其妙WA了
这里树上某节点hash值代表的是这棵子树所代表的序列hash值
求LCP时,只要二分答案然后提取区间判断hash是否相同即可,实践证明错误率很小
这里注意要尽量少取模运算,否则会TLE
1 const mo=9875321; 2 var son:array[-1..100010,1..2] of longint; 3 count,fa,hash,a:array[-1..100010] of longint; 4 d:array[0..100010] of longint; 5 m,n,root,i,x,y,s:longint; 6 ch:char; 7 8 procedure update(x:longint); 9 var l,r:longint; 10 begin 11 l:=son[x,1]; 12 r:=son[x,2]; 13 count[x]:=count[l]+count[r]+1; 14 hash[x]:=hash[l]+a[x]*d[count[l]]+int64(hash[r])*int64(d[count[l]+1]) mod mo; //计算hash 15 hash[x]:=hash[x] mod mo; 16 end; 17 18 function find(k:longint):longint; 19 var p:longint; 20 begin 21 p:=root; 22 while true do 23 begin 24 if count[son[p,1]]+1=k then exit(p); 25 if count[son[p,1]]+1>k then p:=son[p,1] 26 else begin 27 k:=k-count[son[p,1]]-1; 28 p:=son[p,2]; 29 end; 30 end; 31 end; 32 33 procedure rotate(x,w:longint); 34 var y:longint; 35 begin 36 y:=fa[x]; 37 if fa[y]<>-1 then 38 begin 39 if son[fa[y],1]=y then son[fa[y],1]:=x 40 else son[fa[y],2]:=x; 41 end 42 else root:=x; 43 fa[x]:=fa[y]; 44 son[y,3-w]:=son[x,w]; 45 if son[x,w]<>-1 then fa[son[x,w]]:=y; 46 son[x,w]:=y; 47 fa[y]:=x; 48 update(y); 49 end; 50 51 procedure splay(x,f:longint); 52 var y:longint; 53 begin 54 while fa[x]<>f do 55 begin 56 y:=fa[x]; 57 if fa[y]=f then 58 begin 59 if son[y,1]=x then rotate(x,2) 60 else rotate(x,1); 61 end 62 else begin 63 if son[fa[y],1]=y then 64 begin 65 if son[y,1]=x then rotate(y,2) else rotate(x,1); 66 rotate(x,2); 67 end 68 else begin 69 if son[y,1]=x then rotate(x,2) else rotate(y,1); 70 rotate(x,1); 71 end; 72 end; 73 end; 74 update(x); //这是学LCT的时候发现的一个优化,每次rotate只要update父节点即可,这样一下子快了2s多 75 end; 76 77 procedure insert(x,y:longint); 78 begin 79 x:=find(x+1); 80 splay(x,-1); 81 inc(n); 82 a[n]:=y; 83 son[n,2]:=son[x,2]; 84 fa[son[x,2]]:=n; 85 son[x,2]:=n; 86 fa[n]:=x; 87 update(n); 88 update(x); 89 end; 90 91 procedure change(x,y:longint); 92 begin 93 x:=find(x+1); 94 splay(x,-1); 95 a[x]:=y; 96 update(x); 97 end; 98 99 function build(l,r:longint):longint; 100 var m:longint; 101 begin 102 m:=(l+r) shr 1; 103 build:=m; 104 if l<=m-1 then 105 begin 106 son[m,1]:=build(l,m-1); 107 fa[son[m,1]]:=m; 108 end; 109 if m+1<=r then 110 begin 111 son[m,2]:=build(m+1,r); 112 fa[son[m,2]]:=m; 113 end; 114 update(m); 115 end; 116 117 function check(x,l,r:longint):longint; 118 var y:longint; 119 begin 120 y:=find(l+r+1); 121 splay(x,-1); 122 splay(y,x); 123 exit(hash[son[y,1]]); 124 end; 125 126 function ask(x,y:longint):longint; 127 var l,r,m,wx,wy:longint; 128 begin 129 l:=0; 130 r:=n-y; 131 if n-x<r then r:=n-x; 132 ask:=0; 133 wx:=find(x); 134 wy:=find(y); 135 while l<=r do 136 begin 137 m:=(l+r) shr 1; 138 if check(wx,x,m)=check(wy,y,m) then 139 begin 140 l:=m+1; 141 ask:=m; 142 end 143 else r:=m-1; 144 end; 145 end; 146 147 begin 148 fillchar(son,sizeof(son),255); 149 fillchar(fa,sizeof(fa),255); 150 read(ch); 151 while (ch>='a') and (ch<='z') do 152 begin 153 inc(n); 154 a[n]:=ord(ch)-96; 155 read(ch); 156 end; 157 readln(m); 158 d[0]:=1; 159 for i:=1 to 100001 do 160 d[i]:=d[i-1]*29 mod mo; 161 root:=build(0,n+1); 162 inc(n); 163 for i:=1 to m do 164 begin 165 read(ch); 166 if ch='Q' then 167 begin 168 readln(x,y); 169 writeln(ask(x,y)); 170 end 171 else if ch='I' then 172 begin 173 read(x); 174 read(ch); 175 readln(ch); 176 y:=ord(ch)-96; 177 insert(x,y); 178 end 179 else if ch='R' then 180 begin 181 read(x); 182 read(ch); 183 readln(ch); 184 y:=ord(ch)-96; 185 change(x,y); 186 end; 187 end; 188 end.