线性动态规划:最长有效括号匹配子串的变种——允许最多k次失配的最长有效括号子串(进阶版:失配位置可修复)
字数 891 2025-11-04 08:32:42
线性动态规划:最长有效括号匹配子串的变种——允许最多k次失配的最长有效括号子串(进阶版:失配位置可修复)
题目描述:
给定一个只包含'('和')'的字符串s和一个非负整数k,要求找到最长的子串,使得这个子串可以通过最多k次字符修改(将'('改为')'或将')'改为'(')变成一个完全有效的括号字符串。
解题过程:
- 问题分析:
- 这是一个带容错机制的有效括号匹配问题
- 传统有效括号匹配要求左右括号严格匹配,这里允许最多k次修改
- 修改操作可以理解为"修复"不匹配的括号
- 关键观察:
- 我们需要同时跟踪括号的平衡度和已使用的修改次数
- 定义dp[i][j][b]表示考虑前i个字符,使用了j次修改,当前平衡度为b时的最长有效子串长度
- 但三维DP复杂度较高,需要优化
- 优化思路:
- 使用二维DP:dp[i][j]表示以第i个字符结尾,使用了j次修改时的最大平衡度
- 平衡度表示未匹配的'('数量,有效时平衡度应为0
- 同时记录每个状态的最长有效长度
- 状态定义:
- 定义两个二维数组:
- balance[i][j]:以i结尾,使用j次修改时的最大平衡度
- maxLen[i][j]:以i结尾,使用j次修改时的最长有效长度
- 状态转移:
对于每个位置i和修改次数j(0 ≤ j ≤ k):
- 如果s[i] == '(':
- 不修改:平衡度+1,长度+1
- 修改为')':平衡度-1,长度+1,使用次数+1
- 如果s[i] == ')':
- 不修改:平衡度-1,长度+1
- 修改为'(':平衡度+1,长度+1,使用次数+1
平衡度约束:平衡度不能为负,如果为负说明无效
- 初始化:
- balance[0][0] = 0, maxLen[0][0] = 0
- 其他初始为-∞(无效状态)
- 算法步骤:
初始化所有balance为-∞,maxLen为0
对于i从0到n-1:
对于j从0到k:
如果balance[i][j]有效:
# 处理当前字符
ch = s[i]
# 情况1:不修改当前字符
if ch == '(':
new_balance = balance[i][j] + 1
if new_balance >= 0: # 平衡度有效
更新balance[i+1][j]和maxLen[i+1][j]
else: # ch == ')'
new_balance = balance[i][j] - 1
if new_balance >= 0:
更新balance[i+1][j]和maxLen[i+1][j]
# 情况2:修改当前字符(如果j < k)
if j < k:
if ch == '(':
new_balance = balance[i][j] - 1 # 改为')'
if new_balance >= 0:
更新balance[i+1][j+1]和maxLen[i+1][j+1]
else: # ch == ')'
new_balance = balance[i][j] + 1 # 改为'('
if new_balance >= 0:
更新balance[i+1][j+1]和maxLen[i+1][j+1]
记录所有平衡度为0的状态中的最大maxLen值
- 复杂度分析:
- 时间复杂度:O(n×k),n为字符串长度
- 空间复杂度:O(n×k),可优化到O(k)
- 边界情况处理:
- 空字符串:返回0
- k=0时退化为标准的最长有效括号子串问题
- 平衡度必须始终非负
这个算法通过动态规划同时跟踪括号平衡度和修改次数,找到了在有限修改次数下的最长有效括号子串。