P5840 [COCI2015]Divljak

P5840 [COCI2015]Divljak(AC自动机+LCA+BIT)

我们发现对 (T) 集合建 AC 自动机非常的不好做(又要动态),所以我们考虑对 (S) 建 AC 自动机,然后每个 (T) 加入的时候都相当于修改一些节点的权值。

这里我们可以差分一下,把求点转化成求子树和,也就是把每次加入的 (T) 对应的 (假设为)序列 (p) 的地方都加上 1 的贡献。

所以可以发现对于所有的询问其实就是在询问 (S_k) 的子树和。

但是这里我们要避免统计同一个串两次,所以根据树上差分的思路,我们要把 (LCA(p_i,p_{i-1})) 处的点消去 1 的贡献 以及在 (Fa[LCA(p_i,p_{i-1})]) 处再消去 1 的贡献。

然后就是树状数组维护一下和就行了,记得还要树剖(因为统计子树嘛)。

坑点:树剖里更新 (son) 数组的时候注意判 (0) ,因为这个时候 (0) 节点有意义(代表 Fail 树的根节点)。

Trick(拓展)

关于在 LCA 处消去贡献的那一步,实际上先清楚我们这么做的目的:一个串在一次统计中只算一次。

而对于这个有个技巧就是我们必须先把该串对应的所有前缀对应的节点编号存下来,然后按照 dfn 序排序再按照上文的办法消去,这样消除才是正确的。

这个 Trick 非常实用,请务必记住。

原文地址:https://www.cnblogs.com/Akmaey/p/14678495.html