cf587f-solution

CF587F Solution

link

考虑离线,把每个询问拆成 \([1,r]\) 的答案减去 \([1,l)\) 的答案。这样每个询问变成两个小询问。

然后我们扫描线。从 \(1\)\(n\) 分别加入字符串同时回答上述小询问。

接下来的问题处理起来比较棘手。设 \(m=\sum|s_i|\),对 \(|s_k|\) 根号分治:

\(|s_k|\le\sqrt m\),我们试着用 \(\mathcal O(|s_k|)\) 的算法处理这部分。

一开始我们建出所有串的 ACAM,扫描线新加进字符串时把它对应节点的 fail 子树贡献加 \(1\),查询直接对所有文本串经过的节点求贡献和即可。

使用根号区间修改 \(\mathcal O(1)\) 单点查询的分块可以做到 \(\mathcal O(m\sqrt m)\)

\(|s_k|>\sqrt m\),这样的 \(k\) 仅有 \(\mathcal O(\sqrt m)\) 种。

对于这些 \(k\),我们每次把文本串放 ACAM 上跑,把经过的结点打上 tag,pushup 统计每个节点 fail 子树内 tag 数量,对于 \(i\in[1,n]\) 预处理出现次数即可。

这部分也是 \(\mathcal O(n\sqrt m)\)

最后复杂度线性根号。

posted @ 2024-02-27 20:20  iorit  阅读(8)  评论(0)    收藏  举报