【Codeforces710F】String Set Queries 多解

题目大意

N N N个操作。
1.插入一个串 S S S
2.删除一个串 S S S
3.询问未被删除的串在 S S S中出现的次数。
∑ ∣ S ∣ ≤ 3 e 5 \sum |S| \leq 3e5 S3e5,强制在线。

Solution

此题有多种解法,这里例举说明几种。(设 L L L为总长)

Solution 1

如果不强制在线,那么 A C AC AC自动机,后缀自动机都可以做此问题。(对于删除可以再建一个专门的删除的串的自动机,然后答案相减)现在考虑如果强制在线,发现并不好维护,但是由于每个串之间的贡献相互独立,所以可以用到一个很好的技巧:二进制分组。
大意是这样的:假设现在有 q q q个串,我们维护 l o g log log个自动机,对于q的二进制 q 0 q 1 . . . q x q_0q_1...q_x q0q1...qx,如果 q i q_i qi 1 1 1,那么第 i i i个自动机就是 2 i 2^i 2i个串的自动机。相当于说将 q q q个串分到 l o g log log个组中,分组的依据就是 q q q的二进制拆分。那么假设我们现在要插入第 q + 1 q+1 q+1个串,那么类似二进制进位,每次暴力重构即可。
具体的,(在插入 q + 1 q+1 q+1之前)如果第 0 0 0个自动机存了 1 1 1个串,那么将其合并到第 1 1 1个自动机(同时清空第 0 0 0个自动机),在这之后,如果第 1 1 1个自动机存了 2 2 2个串,那么将其合并到第 2 2 2个自动机(同时清空第 1 1 1个自动机),依次类推。每次合并直接暴力重构。
复杂度分析也很明显,一个串最多被重构 l o g log log次(因为每次重构都要向后移动一位,只有 l o g log log位),所以复杂度是对的。

Solution 1.1

A C AC AC自动机即可

Solution 1.2

用后缀自动机。

Solution 2

考虑用后缀自动机怎么做,是不是每次查询 f a i l fail fail树上到根的链?所以我们用 l c t lct lct维护 f a i l fail fail树即可。
注意在线构造后缀自动机要判这个节点是否存在以及在线构造复杂度上界是 O ( L L ) O(L\sqrt{L}) O(LL )
复杂度 O ( L L + L l o g L ) O(L \sqrt{L} + LlogL) O(LL +LlogL)

Solution 3

考虑根号分治,常见的,如果一个串长度大于 L \sqrt{L} L ,那么这样的串不会超过 L \sqrt{L} L 个,否则其长度会小于 L \sqrt{L} L

Solution 3.1

对于插入的一个串,如果长度大于 L \sqrt{L} L ,那么对其建出 K M P KMP KMP数组。否则将其插入 t r i e trie trie中。
对于查询,对于长度大于根号的,直接 K M P KMP KMP跑,注意此时复杂度是 L × l e n a s k \sqrt{L} \times len_{ask} L ×lenask。然后对于长度小于根号的,直接枚举查询串的一个后缀,然后直接在 t r i e trie trie上走,注意到这里 t r i e trie trie的深度小于 L \sqrt{L} L
所以总的复杂度 L L L\sqrt{L} LL

Solution 3.2

考虑后缀自动机。对于一个串,如果其长度小于 L \sqrt{L} L ,那么直接在自动机上跳 f a i l fail fail暴力查询,这样复杂度为 l e n 2 len^2 len2。否则直接在后缀自动机上把相关的链的值重新算一遍(即 d f s dfs dfs一遍),这种操作不超过 L \sqrt{L} L 次。所以总的复杂度还是 L \sqrt{L} L

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值