CF587F Duff is Mad

Posted gzezFISHER

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF587F Duff is Mad相关的知识,希望对你有一定的参考价值。

更好的阅读体验

题意

给定 \\(n\\) 个字符串 \\(S_1...n\\).
定义 \\(\\textoccur(t, s)\\) 为 字符串 \\(t\\) 在字符串 \\(s\\) 中的出现次数. 有 \\(q\\) 次询问,每次给出 \\(l\\)\\(r\\)\\(k\\),输出 \\(\\sum\\limits_l\\le i\\le r\\textoccur(s_i, s_k)\\).

\\(n,k,\\sum |s_i|\\le 10^5\\)

题解

我们对所有串建立fail树

\\(p_i,j\\) 表示串 \\(s_i\\) 的前 \\(j\\) 个字符在AC自动机上对应点的编号,\\(end_i\\) 表示串 \\(s_i\\) 在AC自动机上对应点的编号

\\[\\sum_l\\le i\\le r\\textoccur(s_i, s_k)=\\sum_l\\le i\\le r\\sum_1\\le j\\le \\textsize_k\\textisanc(end_i, p_k, j) \\]

其中 \\(\\textisanc(x, y)\\) 表示在fail树上 \\(x\\) 是否为 \\(y\\) 的祖先

看到 \\(\\sum |s_i|\\le 10^5\\) 这条限制,容易想到对于 \\(|s_k|\\) 根号分治

\\(M=\\sum |s_i|\\)

  • \\(|s_k|<=T\\)
    容易得到一种做法,\\(\\forall l\\le i\\le r\\),对所有以 \\(end_i\\) 为根的子树的所有点加1,然后查询所有 \\(p_k,i\\) 点上的值之和
    把每个询问差分为成 \\([1, l-1]\\)\\([1, r]\\) 两个区间,然后离线下来按右端点排序,维护区间修改单点查询
    树状数组可以做到 \\(\\mathcalO(qT\\log M+n\\log M)\\),当然更快的做法是分块的 \\(\\mathcalO(qT+n\\sqrtM)\\)
  • \\(|s_k|>T\\)
    满足这个条件的 \\(k\\) 数量是 \\(\\mathcalO(\\fracMT)\\) 级别的,因此我们考虑对所有的 \\(k\\) 预处理
    考虑另一种做法,把所有 \\(p_k,i\\) 标上1,然后查询 \\(\\forall l\\le i\\le r\\)\\(end_i\\) 子树和之和
    预处理时我们对 \\(end_i\\) 的子树和做前缀和,询问的差分即可
    \\(\\mathcalO(q+\\fracMT\\times n)\\)

选择一个合适的 \\(T\\),我们视 \\(n\\)\\(M\\)\\(q\\) 为同阶,\\(T\\)\\(\\sqrtM\\) 即可
复杂度可以简单地认为是 \\(\\mathcalO(n\\sqrtM)\\)

代码 codeforces submission 144319232

不忘初心 砥砺前行

以上是关于CF587F Duff is Mad的主要内容,如果未能解决你的问题,请参考以下文章

CF587FDuff is Mad AC自动机+分块

cf 588E Duff in the Army 树上倍增

python 速度测试ping然后发布到Twitter - http://arstechnica.com/business/2016/01/cable-lobby-is-really-mad-ab

xsy 2414CF587CDuff in the Army

Codeforces Round #326 (Div. 2)-Duff and Meat

循环展开或 duff 可以帮助这种情况吗?