Gemini永久会员 C++返回最长有效子串长度

以下是使用动态规划解决最长有效括号子串长度的C++实现,包含详细注释和示例测试:

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

int longestValidParentheses(string s) {
    int n = s.size();
    if (n <= 1) return 0;
    
    vector<int> dp(n, 0); // dp[i]表示以s[i]结尾的最长有效括号长度
    int max_len = 0;
    
    for (int i = 1; i < n; ++i) {
        if (s[i] == ')') {
            if (s[i-1] == '(') {
                // 情况1:形如 "...()"
                dp[i] = (i >= 2) ? dp[i-2] + 2 : 2;
            } else {
                // 情况2:形如 "...))"
                int prev_len = dp[i-1];
                int prev_start = i - prev_len;
                if (prev_start > 0 && s[prev_start-1] == '(') {
                    dp[i] = dp[i-1] + 2;
                    // 如果前面还有有效序列,可以合并
                    if (prev_start - 2 >= 0) {
                        dp[i] += dp[prev_start-2];
                    }
                }
            }
            max_len = max(max_len, dp[i]);
        }
        // 如果是'(',dp[i]保持为0
    }
    
    return max_len;
}

// 优化空间版本(使用栈的思想,但保持DP解法)
int longestValidParenthesesOptimized(string s) {
    int n = s.size();
    vector<int> dp(n, 0);
    int max_len = 0;
    
    for (int i = 1; i < n; ++i) {
        if (s[i] == ')') {
            if (s[i-1] == '(') {
                dp[i] = (i >= 2 ? dp[i-2] : 0) + 2;
            } else {
                int len = dp[i-1];
                if (i - len > 0 && s[i - len - 1] == '(') {
                    dp[i] = dp[i-1] + 2 + ((i - len - 2 >= 0) ? dp[i - len - 2] : 0);
                }
            }
            max_len = max(max_len, dp[i]);
        }
    }
    
    return max_len;
}

int main() {
    vector<string> test_cases = {
        "(()",       // 2
        ")()())",    // 4
        "",          // 0
        "()(())",    // 6
        "()(()",     // 2
        "((()))())", // 8
        "()((())",   // 6
    };
    
    for (const auto& s : test_cases) {
        cout << "Input: \"" << s << "\"\n";
        cout << "Output: " << longestValidParentheses(s) << "\n";
        cout << "Optimized Output: " << longestValidParenthesesOptimized(s) << "\n\n";
    }
    
    return 0;
}

关键点说明:

  1. 动态规划定义

    • dp[i] 表示以 s[i] 结尾的最长有效括号子串长度
    • 初始化全为0,因为只有遇到)才可能形成有效子串
  2. 两种情况处理

    • 情况1...()
      • s[i] == ')'s[i-1] == '('时,直接形成新配对
      • 长度 = 前前位置的值 + 2
    • 情况2...))
      • s[i] == ')'s[i-1] == ')'时,需要检查是否能与更前面的(配对
      • 计算前一个有效长度prev_len = dp[i-1]
      • 检查s[i-prev_len-1]是否是(
  3. 边界处理

    • 访问dp[i-2]dp[prev_start-2]时要确保索引不越界
    • 空字符串或单字符字符串直接返回0
  4. 优化空间

    • 第二个实现是空间优化版本,但保持了相同的DP思路
    • 实际项目中可以使用更高效的栈方法(O(1)空间)

复杂度分析:

  • 时间复杂度:O(n)(单次遍历字符串)
  • 空间复杂度:O(n)(DP数组)

示例输出:

复制代码
Input: "(()"
Output: 2
Optimized Output: 2

Input: ")()())"
Output: 4
Optimized Output: 4

Input: ""
Output: 0
Optimized Output: 0

Input: "()(())"
Output: 6
Optimized Output: 6

Input: "()(()"
Output: 2
Optimized Output: 2

Input: "((()))()"
Output: 8
Optimized Output: 8

Input: "()((())"
Output: 6
Optimized Output: 6

这个实现正确处理了各种边界情况,包括嵌套括号和连续有效子串的合并。

相关推荐
KingRumn7 小时前
Linux信号之标准信号与实时信号
linux·算法
上进小菜猪8 小时前
面向课堂与自习场景的智能坐姿识别系统——从行为感知到可视化部署的完整工程【YOLOv8】
后端
BestAns9 小时前
一文带你吃透 Java 反射机制
java·后端
沐知全栈开发9 小时前
HTML5 浏览器支持
开发语言
wasp5209 小时前
AgentScope Java 核心架构深度解析
java·开发语言·人工智能·架构·agentscope
WHOVENLY9 小时前
【javaScript】- 笔试题合集(长期更新,建议收藏,目前已更新至31题)
开发语言·前端·javascript
2501_9167665410 小时前
【Springboot】数据层开发-数据源自动管理
java·spring boot·后端
慌糖10 小时前
流-为序列化解释
开发语言
半夏知半秋10 小时前
docker常用指令整理
运维·笔记·后端·学习·docker·容器
程序员码歌10 小时前
短思考第263天,每天复盘10分钟,胜过盲目努力一整年
android·前端·后端