给定字符串 s 和序列 w ,初始均为空。
总共 n 次操作,每次在 s 末端添加一个小写字符 c ,在 w 末端添加一个整数 w ,每次添加后求出所有满足 s[1,r−l+1]=s[l,r] 的区间 [l,r] 的最小值之和。
强制在线。
其中 1≤n≤6⋅105,0≤w≤230−1,c∈[a,z] 。
思路
考虑到条件 s[1,r−l+1]=s[l,r] 不难想到每次添加字符后的答案即为上一次的答案加上当前串的所有 border 的贡献。
那么需要每次添加字符时实时维护当前串的 border 集合 T 与它们的总贡献 sum 。
对于 T ,考虑添加一个字符后,对于 T 中的每一个 border ,若它的后一个字符不是 c ,则需要将它从 T 中删除,而如果有 c=s[1] 则需要将 1 也加入集合。对于每次添加操作,最多会往集合中加入一个数,每个数最多被删去一次,所以维护 T 的复杂度是均摊 O(n) 的。
对于删去不满足条件的 border 的操作,可以考虑在维护 fail 数组的同时维护一个 pre 数组,其中 prei 表示前 i−1 个字符组成的前缀的 border 集合中最长的不满足条件的 border 长度,每次暴力遍历 pre 即可,由于均摊操作复杂度有保证。
对于 sum ,考虑删去 T 中的一个 border 后需要减掉其对应的贡献,这个可以用一个单调栈 + 二分解决,对于剩下的 border 均往后拓展了一位,需要将其贡献与 w 取 min ,若新添加 1 则需要加上 w 的贡献。
对于将贡献与 w 取 min 的操作,可以考虑对每种贡献 w′ 用 map 记录一个数量,每次暴力将 map 中大于 w 的数更新为 w 。由于每种数字只会被更新一次(更新完即合并了),所以加上 map 的复杂度后维护 sum 的复杂度是均摊 O(n⋅logn) 的。
注意结果可能会爆 longlong ,用 int128 存答案即可,维护的总复杂度为 O(n⋅logn) 。