HNOI2019 JOJO [* easy]
给定一个空串 (s),支持在结尾插入 (x) 个 (c),以及回溯到第 (t) 次操作时的局面,每次操作后输出当前串中所有 next 数组的和。
保证 (c) 不等于当前的结尾字符。
(nle 10^5,xle 10^4, cin {asim z})
Solution
考虑使用 (a,x,b,y,c,z) 的形式来描述字符串,其中 (a,b,c) 均为字符,同时 (x,y,z) 均为数字。
先考虑不带回溯的版本,对于一次插入操作,我们考虑定位 (a,x,b,y,c,z+d) 时,仅考虑 (d) 为结尾的情况下的 fall 树祖先,我们考虑每个祖先接下来接的数字,并将其描述为此祖先的权值。
不难发现此时问题可以等价于:我们给定数字 (x),对于 (i=1,2,3...x) 计算满足第一个点权大于等于其的祖先的深度,我们通过可持久化线段树加上标记永久化可以解决此问题。
我们只需要定位 fall 树上的祖先即可,注意到题面保证当前插入的串必然不为结尾,所以我们可以直接将 “数字字符” 作为真正的字符并用于匹配,此时我们只需要定位此字符,在读入字符 (c) 之后匹配的节点即可。
由于不带回溯,此过程通过 kmp 来实现将得到正确的复杂度,我们可以在 (mathcal O(nlog n)) 的复杂度解决不带回溯的版本。
不难注意到增加回溯之后,我们可以将这个字符串魔改成一个 trie 树,此时我们只需要支持快速的建立这个 trie 树的 fall 树即可,动态操作难以解决,我们考虑将操作离线,此时我们只需要快速建立一个字符集非常大的 trie 树的 fall 树即可。
这个流程可以通过主席树来加速,注意到其本质上可以认为是树链统计第一个出现的颜色位置这一问题,使用主席树维护颜色即可,复杂度 (mathcal O(nlog n))