bzoj1014

动态询问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.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473032.html