1 条题解
-
0
题目理解
我们要求的是:对于字符串 的每一个子串,统计它有多少种优秀的拆分,然后把所有子串的优秀拆分个数加起来。
一个优秀的拆分是:子串可以写成 形式,其中 和 非空。
思路分析
1. 暴力方法
枚举所有子串 ,再枚举拆分点,判断是否满足 形式。
复杂度 或 ,显然不可行。2. 转化问题
可以看作两个 形式的串拼接而成,中间切一刀:
设切点在 和 之间,那么前半部分 的某个后缀是 ,后半部分 的某个前缀是 。更精确地,对于一个固定的切分位置 (即 中第一个 开始的位置的前一个位置),我们要数有多少对 使得:
这样还是复杂,我们换一种思路。
3. 关键观察
可以看作在某个位置 切分,左边是 的结束位置,右边是 的开始位置。
具体来说,设 是第一个 的开头位置的前一个位置(即 的结尾位置),那么:
- 在 处结束的形如 的串的个数,记作
- 在 处开始的形如 的串的个数,记作
那么以 为 与 的分界点,优秀拆分的个数就是 。
因此,问题转化为:
- 对每个位置 ,计算有多少个 以 结尾 →
- 对每个位置 ,计算有多少个 以 开头 →
- 答案
4. 如何求 和
求所有 型子串的出现位置,是一个经典问题。
方法: 使用后缀数组 (Suffix Array) + 高度数组 (LCP) 或 哈希 + 枚举长度。
枚举长度法
枚举 的长度 ,那么 由两个相同子串拼接,中间切点在某个位置。
我们枚举 ,然后在字符串上以步长 设置关键点,相邻关键点求最长公共前缀 (LCP) 和最长公共后缀 (LCS),就可以得到 出现的区间。
具体做法(常见套路):
- 设关键点为 和
- 计算 和
- 通过 LCP 和 LCS 可以确定 覆盖的区间,然后用差分数组标记这些 的起始和结束位置。
这样我们就能得到:
- 以 结尾的 个数
- 以 开头的 个数
5. 复杂度
枚举 从 到 ,内部 个关键点,每个关键点求 LCP/LCS 如果用哈希+二分是 ,总复杂度 ,可过 。
如果用后缀数组 + ST 表求 LCP,可以做到 。
6. 算法步骤
- 读入多组数据。
- 对每组数据:
- 初始化 ,
- 枚举 到 :
- 对 且 :
- 计算
- 计算
- 确定 出现的区间,更新 和 的差分数组
- 对 且 :
- 对差分数组求前缀和得到真正的 和
- 计算 ,输出答案
- 1
信息
- ID
- 4849
- 时间
- 1500ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者