【Codeforces710F】String Set Queries 多解

本文探讨了处理字符串操作的在线算法,包括AC自动机、后缀自动机和根号分治等方法,适用于插入、删除及查询字符串出现次数的问题。文章详细分析了不同算法的实现细节与复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

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

Solution

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

Solution 1

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

Solution 1.1

ACACAC自动机即可

Solution 1.2

用后缀自动机。

Solution 2

考虑用后缀自动机怎么做,是不是每次查询failfailfail树上到根的链?所以我们用lctlctlct维护failfailfail树即可。
注意在线构造后缀自动机要判这个节点是否存在以及在线构造复杂度上界是O(LL)O(L\sqrt{L})O(LL)
复杂度O(LL+LlogL)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,那么对其建出KMPKMPKMP数组。否则将其插入trietrietrie中。
对于查询,对于长度大于根号的,直接KMPKMPKMP跑,注意此时复杂度是L×lenask\sqrt{L} \times len_{ask}L×lenask。然后对于长度小于根号的,直接枚举查询串的一个后缀,然后直接在trietrietrie上走,注意到这里trietrietrie的深度小于L\sqrt{L}L
所以总的复杂度LLL\sqrt{L}LL

Solution 3.2

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值