1 条题解
-
0
题解:动态维护子串的
bessie匹配数问题转化
定义 为从字符串 中删除若干字符后能得到的形如
bessie重复串中bessie的最大出现次数。。
支持单点修改 的字符,每次询问修改后的 。
。
关键观察
等价于按顺序匹配
bessie这个单词能匹配多少次。设模式串 ,长度 。
就是 作为序列,能完整匹配 的最大次数,允许跳过字符。
自动机模型
建立自动机:状态 表示未开始匹配,状态 表示已匹配到
bessie的第 个字符。状态 匹配完一个bessie后回到状态 (因为可以连续匹配)。实际上:匹配完一次
bessie后,最后一个e同时也是下一个bessie中b的前一个字符,所以状态转移是:- 在状态 ,若下一个字符等于 (下标从 1 开始),则转移到状态 (若 则转移到状态 并计数 +1)。
- 否则停留在状态 (跳过字符)。
但为了统计 的值,我们需要知道在扫描 时能完成多少次完整匹配。
动态规划计算
设 表示扫描到当前位置时,已经匹配了 个
bessie的字符(, 时再遇到e就完成一次)。
但为了计算 ,我们需要知道最大匹配次数,这等价于贪心匹配:尽可能早地完成每一次bessie。所以 就是从左到右贪心匹配
bessie能得到的次数。计算所有子串的 和
考虑每个子串 ,它的 值就是从左到右扫描该子串能匹配到的
bessie个数。固定左端点 ,当右端点 右移时, 可能增加(当完成一次
bessie匹配时)。定义 为从位置 开始贪心匹配一个
bessie结束的位置的下一个位置(即匹配完一次bessie后的下一个位置)。若无法匹配则 。则 等于从 开始,不断跳 直到超过 的跳跃次数。
转化为计数问题
$A(t) = \sum_{l\le r} B(t[l..r]) = \sum_{l} \sum_{r\ge l} B(t[l..r])$。
固定 ,考虑右端点 从 到 移动, 是一个分段常数函数,每当 经过一个 跳跃点时增加 。
设从 开始能匹配到 个
bessie,第 个bessie的结束位置为 (即跳 次 后的位置的前一个位置),则:- 对于 ,
- 对于 ,
- ...
- 对于 ,
- 对于 ,
所以固定 的贡献为:
其中 。
计算总贡献
$A(t) = \sum_{l=1}^n \sum_{i=1}^{k_l} i \times (e_{l,i+1} - e_{l,i})$。
交换求和顺序:
$$A(t) = \sum_{i\ge 1} i \times \sum_{l} (e_{l,i+1} - e_{l,i}) $$其中 是从 开始第 个
bessie的结束位置。高效维护
考虑每个
bessie的出现对答案的贡献。若一个
bessie覆盖区间 (从位置 的b开始到位置 的e结束),则它对哪些子串 的 值有贡献?当 且 时,这个
bessie会被统计在 中。但还要考虑在 内它是第几个bessie。更简单的想法:考虑每个
bessie的出现,它作为第 个bessie对答案贡献为 包含它作为第 个bessie的子串个数。自动机 + 数据结构
建立
bessie的自动机,状态 表示已匹配的字符数。扫描字符串,维护每个位置 的自动机状态 。
对于每个位置 ,若 使自动机从状态 (已匹配
bessi)转移到状态 (完成一个bessie),则说明 是一个bessie的结束位置。设这个
bessie的开始位置为 ,则从任意 且 的子串都会包含这个完整的bessie。但 中这个
bessie是第几个?这取决于在 中已完成了多少个bessie。最终算法
- 预处理
bessie的自动机。 - 扫描字符串,记录每个
bessie出现的开始位置 和结束位置 。 - 维护一个数组 表示当前位置作为左端点时,已经完成了 个
bessie的左端点个数。 - 从左到右扫描右端点 :
- 若 是一个
bessie的结束位置,则它对答案的贡献为 (因为它作为第 个bessie被统计)。 - 然后更新 :所有 的左端点完成数 ,即 转移到 。
- 若 是一个
- 用线段树或 Fenwick 树维护 数组的区间和与区间平移操作。
单点修改时,重新计算受影响区间的
bessie出现情况,更新数据结构。复杂度
- 预处理
- 每次修改影响 个
bessie(),更新 - 总复杂度
- 1
信息
- ID
- 6081
- 时间
- 4000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者