CF587F Duff is Mad

  • 给定 \(n\) 个字符串 \(s_{1 \dots n}\)
  • \(q\) 次询问 \(s_{l \dots r}\)\(s_k\) 中出现了多少次。
  • \(n,q,\sum_{i=1}^n |s_i| \le 10^5\)

  字符串 根号分治

  首先,建立 AC 自动机。

  考虑暴力,就是将 \(s_{l\sim r}\) 的在 AC 自动机的终止节点的子树权值 +1,然后答案就是 \(s_k\) 在 AC 自动机上面对应路径的权值之和。

  考虑差分之后扫描线,我们只要支持求将 \(s_{1 \sim cur}\) 的终止节点子树权值 \(+1\) 后,\(s_k\) 在 AC 自动机上面对应路径的权值之和了。

  然后复杂度是 \(\mathcal O(\max\{|S_i|\} q \log_2 L)\) 的,其中 \(L = \sum |S_i|\)

  本来想使用树链剖分进行进一步优化的,但是因为 AC 自动机的路径在 Fail 树上不连续,因此我们只能暴跳然后求和。

  但是我们可以根据字符串长度考虑根号分治

  具体地,对于 \(|s_k| \ge B\),我们可以将这些串对应的询问单独拿出来,然后将 \(s_k\) 在 AC 自动机上面对应的路径权值 +1,然后在对于每个 \(i\),求出如果 \(i \in [l, r]\)\(s_i\) 对于 \(s_k\) 的答案的贡献,这个只要在树上面 DFS 然后前缀和即可求解,总复杂度 \(\mathcal O(\frac{L^2}{B})\)

  对于 \(|s_k| < B\),直接使用暴力,总复杂度就是 \(\mathcal O(q B\log_2 L)\)

  根据均值不等式,当 \(B = \frac{L}{\sqrt{q\log_2 L}}\) 的时候复杂度最优,为 \(\mathcal O(L\sqrt{q\log_2 L})\)

  代码

  当然,如果第一部分写丑了直接树状数组多了个 \(\log_2\),那么也是可以调整块长然后通过的:代码

posted @ 2022-03-17 20:34  Werner_Yin  阅读(54)  评论(0编辑  收藏  举报