某种意义上第一道 LCT?(
考虑类比区间数颜色的做法,将询问离线按右端点排序,逐次考虑每个 [1,r] 的前缀。
对后缀自动机上每个状态 p 维护当前的 maxendpos(p),那么每个字符串 S 对 l∈[1,maxendpos(S)−|S|+1] 的询问有贡献。
问题在于如何维护 maxendpos(p),设这个东西为 last(p),那么从 r−1 转移到 r 相当于修改 Parent Tree 上一条从根开始的链所有状态的 last 值为 r。
如果只要维护 last 值还好,可以直接上树链剖分 + 区间赋值的线段树。
然而我们同时要维护贡献,这就不大妙了。
注意到修改的是从根开始的一条链,这启发我们联想 LCT 的 Access 操作。
发现每条实链上的 last 值是相等的,并且所代表的长度是连续的,又相当于 S1…r 连续的一段后缀。
所以在合并实链的时候直接更新贡献。
此外,贡献实际上是区间加等差数列,单点查询,可以通过差分序列转化为区间加常数,区间查询,然后用 BIT 维护。
根据 LCT 的复杂度,容易发现这是 O(nlog2n) 的。
实现基本参考了 Fuyuki 大佬的代码。
代码:
1 |
|