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})$

代码 codeforces submission 144319232

作者

Fisher Cai

发布于

2022-01-28

更新于

2022-02-19

许可协议

评论

Your browser is out-of-date!

Update your browser to view this website correctly.&npsb;Update my browser now

×