CF587F Duff is Mad
题意
给定 $n$ 个字符串 $S_{1…n}$.
定义 $\text{occur}(t, s)$ 为 字符串 $t$ 在字符串 $s$ 中的出现次数. 有 $q$ 次询问,每次给出 $l$,$r$ 和 $k$,输出 $\sum\limits_{l\le i\le r}\text{occur}(s_i, s_k)$.
$n,k,\sum |s_i|\le 10^5$
题解
我们对所有串建立AC自动机
令 $p_{i,j}$ 表示串 $s_i$ 的前 $j$ 个字符构成的子串在AC自动机上对应点的编号,$end_{i}$ 表示串 $s_i$ 在AC自动机上对应点的编号
$s_i$ 在 $s_k$ 中出现就代表 $s_i$ 是 $s_k$ 某个前缀的后缀,因此有
其中 $\text{isanc}(x, y)$ 表示在fail树上 $x$ 是否为 $y$ 的祖先
看到 $\sum |s_i|\le 10^5$ 这条限制,容易想到对于 $|s_k|$ 根号分治
令 $M=\sum |s_i|$
- $|s_k|\le T$
容易想到一种做法,$\forall l\le i\le r$,对所有以 $end_i$ 为根的子树的所有点加1,然后查询所有 $p_{k,i}$ 点上的值之和
把每个询问差分为成 $[1, l-1]$ 和 $[1, r]$ 两个区间,然后离线下来按右端点排序,维护区间修改单点查询
树状数组可以做到 $\mathcal{O}(qT\log M+n\log M)$,更快的做法是分块 $\mathcal{O}(qT+n\sqrt{M})$ - $|s_k|>T$
满足这个条件的 $k$ 数量是 $\mathcal{O}(\frac{M}{T})$ 级别的,因此考虑对所有的 $k$ 预处理
考虑另一种做法,把所有 $p_{k,i}$ 标上1,然后查询 $\forall l\le i\le r$,$end_i$ 子树和之和
预处理时我们对 $end_i$ 的子树和做前缀和,询问的差分即可
$\mathcal{O}(q+\frac{M}{T}\times n)$
选择一个合适的 $T$,不妨认为 $n$,$M$ 和 $q$ 同阶,$T$ 取 $\sqrt{M}$ 即可
复杂度可以认为是 $\mathcal{O}(n\sqrt{M})$
CF587F Duff is Mad