1 条题解
-
0
问题分析
本题是一道关于字符串处理的综合性问题,核心任务是解决多个查询,每个查询需要统计满足特定条件的字符串子串数量。通过分析代码可知,问题涉及后缀数组(SA)、回文串判定(Manacher算法)和树状数组(BIT)等多种字符串与数据结构技术。
算法思路
1. 核心问题拆解
每个查询要求计算满足条件的子串数量,具体可分解为两部分:
- 统计满足
Suf[i] < Pre[i+2l]
的子串数量(Suf[i]
表示从位置i
到结尾的后缀,Pre[i]
表示从开头到位置i
的前缀反转) - 减去同时满足回文条件
s[i,i+2l)
是回文且Suf[i+2l] < Pre[i]
的子串数量
2. 后缀数组(SA)的应用
使用SAIS算法构建后缀数组,用于高效比较字符串的后缀和前缀:
- 构造拼接字符串
str = s + 'a'-1 + reversed(s) + 'a'-2
,其中reversed(s)
是原字符串的反转 - 通过SAIS算法计算该拼接字符串的后缀数组
sa
和排名数组rank
,其中rank[i]
表示位置i
处后缀的排名 - 利用排名数组可在 时间内比较任意两个后缀的大小关系
3. 第一部分计算(First::solve)
统计满足
Suf[i] < Pre[i+2l]
的子串数量:- 将问题转化为比较
rank[i]
与rank[2n+1-t]
的大小关系 - 对每个查询构造两个事件(开始和结束),记录需要比较的排名和位置
- 使用两个树状数组(
bit[0]
和bit[1]
)分别处理偶数和奇数位置的更新与查询 - 按位置顺序处理事件,通过树状数组的区间查询功能统计满足条件的数量,时间复杂度为
4. 回文串判定(Manacher算法)
使用Manacher算法高效计算所有回文子串:
- 构造扩展字符串(插入特殊字符),统一处理奇数和偶数长度的回文串
- 计算
maxLen[i]
数组,表示以位置i
为中心的最长回文串半径 - 转化得到
R[j]
数组,记录以原字符串位置j
为中心的最长回文串半径
5. 第二部分计算(Second::solve)
统计需要减去的特殊回文子串数量:
- 筛选满足条件的回文子串,记录其有效范围
[l, r]
- 对每个查询构造两个事件(开始和结束),表示需要统计的区间
- 使用树状数组记录回文子串的范围,按位置顺序处理更新和查询
- 通过树状数组的前缀和查询统计有效回文子串数量,时间复杂度为
关键技术细节
-
SAIS算法:线性时间复杂度的后缀数组构造算法,核心是通过分类L型(
L
)和S型(S
)字符,递归处理LMS(Left-Most S-type)子串,实现高效排序。 -
Manacher算法:线性时间复杂度的回文串查找算法,通过利用已知回文串的对称性减少重复比较,核心公式为:
$$\text{maxLen}[i] = \min(\text{maxLen}[l + r - 1 - i], r - i - 1) \quad (\text{当} \, i < r \, \text{时}) $$其中
l
和r
表示当前已知的最右回文串的左右边界。 -
树状数组(BIT):用于高效的区间更新和前缀和查询,支持两种核心操作:
- 单点更新: 时间内更新某个位置的值
- 前缀和查询: 时间内计算某个位置的前缀和
整体复杂度分析
- 后缀数组构造:(SAIS算法)
- Manacher算法:
- 第一部分查询处理:
- 第二部分查询处理:
- 总时间复杂度:,可处理 和 的输入规模
最终答案计算
每个查询的结果为第一部分统计值减去第二部分统计值,即:
$$\text{ans}[i] = \text{count}_1[i] - \text{count}_2[i] $$其中 是满足
Suf[i] < Pre[i+2l]
的数量, 是需要减去的特殊回文子串数量。 - 统计满足
- 1
信息
- ID
- 3276
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者