1 条题解
-
0
「POI2011 R2」差值 Difference 题解
题目解析
我们需要在字符串中找到一个子串,使得该子串中出现次数最多的字母与出现次数最少的字母(必须至少出现一次)的出现次数之差最大。
关键约束:
- 最少出现的字母必须至少出现一次
- 如果子串只有一种字母,差值为0
- 字符串长度可达 ,需要高效算法
算法思路
核心观察
这个问题可以转化为:对于任意两种不同的字母
a和b,找到子串使得a和b的出现次数之差最大。重要思路:
- 只考虑两种字母的情况,因为最优解必然只涉及两种字母(如果涉及三种,去掉出现次数居中的那种不会使差值变小)
- 将问题转化为最大子段和问题
转化方法
对于每对字母
(a, b):- 在字符串中,将
a标记为+1,b标记为-1,其他字母标记为0 - 那么
a和b的出现次数之差就是这个序列的子段和 - 我们需要找到最大的子段和
但是有一个重要限制:子串中必须同时包含
a和b(即+1和-1都要出现)高效解法
我们可以枚举所有26×25=650对字母,但需要 处理每对字母。
优化策略: 对于固定的一对字母
(x, y):-
遍历字符串,维护:
diff:当前x比y多出现的次数min_diff:历史上最小的diff值last_x:最近一次遇到x时的位置last_y:最近一次遇到y时的位置
-
当遇到
x时:diff++当遇到y时:diff--遇到其他字母时:不变 -
关键技巧:只有当
last_x和last_y都出现过时,才能用diff - min_diff更新答案 因为diff - min_diff表示从某个历史位置到当前位置,x比y多出现的最大次数
算法步骤
- 枚举所有字母对
(x, y),其中x ≠ y - 对于每对字母:
- 初始化
diff = 0,min_diff = 0,last_x = -1,last_y = -1,ans = 0 - 遍历字符串:
- 更新
diff和min_diff - 如果当前字符是
x,更新last_x - 如果当前字符是
y,更新last_y - 如果
last_x ≠ -1且last_y ≠ -1,用diff - min_diff更新答案
- 更新
- 初始化
- 输出最大答案
复杂度分析
- 时间复杂度:,对于 是可接受的
- 空间复杂度: 存储字符串
算法特点
- 枚举简化:将复杂的最优化问题简化为枚举字母对
- 转化技巧:将出现次数差转化为子段和问题
- 高效处理:利用历史最小值技巧在 时间内处理每对字母
这种方法充分利用了字母表大小有限的特点,将看似 的问题转化为 的可解问题。
- 1
信息
- ID
- 4336
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者