最长括号匹配子序列问题
字数 1136 2025-11-24 00:42:42

最长括号匹配子序列问题

题目描述:
给定一个只包含 '(' 和 ')' 的字符串 s,找出其中最长的有效括号子序列的长度。有效括号子序列需要满足:

  1. 空序列是有效的
  2. 如果序列 A 是有效的,那么 (A) 也是有效的
  3. 如果序列 A 和 B 都是有效的,那么 AB 也是有效的

解题过程:

  1. 问题分析
    这是一个区间动态规划问题。我们需要在字符串 s 中找到一个子序列(不一定连续),使得这个子序列是有效的括号匹配序列,并且长度最长。

  2. 状态定义
    定义 dp[i][j] 表示在子串 s[i...j] 中最长有效括号子序列的长度。

  3. 状态转移方程
    考虑区间 [i, j] 的最长有效括号子序列,有以下几种情况:

情况1:如果 s[i] 和 s[j] 可以匹配(即 s[i]=='(' 且 s[j]==')')
那么 dp[i][j] = max(dp[i+1][j-1] + 2, dp[i+1][j], dp[i][j-1])

情况2:如果 s[i] 和 s[j] 不能匹配
那么 dp[i][j] = max(dp[i+1][j], dp[i][j-1])

情况3:对于任意区间 [i, j],我们还需要考虑分割点 k
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k+1][j]),其中 i ≤ k < j

  1. 边界条件
  • 当 i > j 时,dp[i][j] = 0(空序列)
  • 当 i = j 时,dp[i][j] = 0(单个括号无法匹配)
  1. 计算顺序
    由于区间动态规划的特性,我们需要按照区间长度从小到大进行计算:
  • 先计算长度为 1 的区间
  • 再计算长度为 2 的区间
  • 依此类推,直到计算整个字符串
  1. 算法实现步骤
    步骤1:初始化 n×n 的 dp 数组,所有元素设为 0
    步骤2:处理长度为 2 的区间
    步骤3:对于每个区间长度 len 从 2 到 n
    步骤4:对于每个起始位置 i 从 0 到 n-len
    步骤5:计算结束位置 j = i + len - 1
    步骤6:如果 s[i] 和 s[j] 匹配,更新 dp[i][j]
    步骤7:考虑所有可能的分割点 k,更新 dp[i][j]
    步骤8:返回 dp[0][n-1]

  2. 时间复杂度分析

  • 需要遍历所有 O(n²) 个区间
  • 每个区间需要检查 O(n) 个分割点
  • 总时间复杂度为 O(n³)
  • 空间复杂度为 O(n²)
  1. 优化思路
    可以通过预处理来优化分割点的查找,但基本的三重循环方法已经能够解决这个问题。

这个算法通过系统地考虑所有可能的子区间和分割方式,确保找到最长的有效括号子序列。

最长括号匹配子序列问题 题目描述: 给定一个只包含 '(' 和 ')' 的字符串 s,找出其中最长的有效括号子序列的长度。有效括号子序列需要满足: 空序列是有效的 如果序列 A 是有效的,那么 (A) 也是有效的 如果序列 A 和 B 都是有效的,那么 AB 也是有效的 解题过程: 问题分析 这是一个区间动态规划问题。我们需要在字符串 s 中找到一个子序列(不一定连续),使得这个子序列是有效的括号匹配序列,并且长度最长。 状态定义 定义 dp[ i][ j] 表示在子串 s[ i...j ] 中最长有效括号子序列的长度。 状态转移方程 考虑区间 [ i, j ] 的最长有效括号子序列,有以下几种情况: 情况1:如果 s[ i] 和 s[ j] 可以匹配(即 s[ i]=='(' 且 s[ j ]==')') 那么 dp[ i][ j] = max(dp[ i+1][ j-1] + 2, dp[ i+1][ j], dp[ i][ j-1 ]) 情况2:如果 s[ i] 和 s[ j ] 不能匹配 那么 dp[ i][ j] = max(dp[ i+1][ j], dp[ i][ j-1 ]) 情况3:对于任意区间 [ i, j ],我们还需要考虑分割点 k dp[ i][ j] = max(dp[ i][ j], dp[ i][ k] + dp[ k+1][ j]),其中 i ≤ k < j 边界条件 当 i > j 时,dp[ i][ j ] = 0(空序列) 当 i = j 时,dp[ i][ j ] = 0(单个括号无法匹配) 计算顺序 由于区间动态规划的特性,我们需要按照区间长度从小到大进行计算: 先计算长度为 1 的区间 再计算长度为 2 的区间 依此类推,直到计算整个字符串 算法实现步骤 步骤1:初始化 n×n 的 dp 数组,所有元素设为 0 步骤2:处理长度为 2 的区间 步骤3:对于每个区间长度 len 从 2 到 n 步骤4:对于每个起始位置 i 从 0 到 n-len 步骤5:计算结束位置 j = i + len - 1 步骤6:如果 s[ i] 和 s[ j] 匹配,更新 dp[ i][ j ] 步骤7:考虑所有可能的分割点 k,更新 dp[ i][ j ] 步骤8:返回 dp[ 0][ n-1 ] 时间复杂度分析 需要遍历所有 O(n²) 个区间 每个区间需要检查 O(n) 个分割点 总时间复杂度为 O(n³) 空间复杂度为 O(n²) 优化思路 可以通过预处理来优化分割点的查找,但基本的三重循环方法已经能够解决这个问题。 这个算法通过系统地考虑所有可能的子区间和分割方式,确保找到最长的有效括号子序列。