随笔 - 540  文章 - 0 评论 - 39 阅读 - 12万
< 2025年1月 >
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

动态询问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
复制代码

 

posted on   acphile  阅读(149)  评论(0编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥
点击右上角即可分享
微信分享提示