最长合法括号子序列

最长合法括号子序列

一个合法的括号序列满足以下条件:

  1. 序列()被认为是合法的。
  2. 如果序列XY是合法的,则XY也被认为是合法的。
  3. 如果序列X是合法的,则(X)也是合法的。

例如, () , ()() , (()) 这些都是合法的。

现在,给定一个由  (  和  )  组成的字符串。

请你求出其中的最长合法括号子序列的长度。

注意,子序列不一定连续。

输入格式

共一行,一个由  (  和  )  组成的字符串。

输出格式

一个整数,表示最长合法括号子序列的长度。

数据范围

前五个测试点满足,1输入字符串的长度10

所有测试点满足,1输入字符串的长度106

输入样例1:

(()))(

输出样例1:

4

输入样例2:

()()(()(((

输出样例2:

6

 

解题思路

  这是一个括号序列的问题。对于一个合法的括号序列,有两个结论:

  1. 整个序列的左右括号数量相等。
  2. 任意一个前缀中,左括号的数量大于等于右括号的数量。

  对于这两个条件,一般用一个计数器来实现。一开始cnt=0,遇到左括号就cnt++,遇到右括号就cnt。等价于在上面的第1个条件中,最后的cnt=0;第2个条件中,整一个操作的过程cnt都始终满足cnt0

  一个合法括号序列最长,等价于右括号数量最多(因为左右括号数量相同),因此我们只需要找到一个合法括号序列,使得右括号的数量最多就可以了。

  贪心的思想是,对于右括号,能选则选。如果在遍历的过程中遇到右括号,且cnt>0,就选这个右括号。下面证明一下这种做法是正确的。

  首先有贪心解最优解,因为贪心解是合法解,最优解是合法解中最大的那一个,因此贪心解最优解。

  下面证明贪心解最优解。反证法,假设有最优解>贪心解。

  因此可以证明得到贪心解最优解,贪心解最优解,即可以证明贪心解=最优解。

  AC代码如下:

复制代码
 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 
 5 const int N = 1e6 + 10;
 6 
 7 char str[N];
 8 
 9 int main() {
10     scanf("%s", str);
11     
12     int l = 0, r = 0;
13     for (int i = 0; str[i]; i++) {
14         if (str[i] == '(') l++;
15         else if (l > 0) l--, r++;
16     }
17     
18     printf("%d", r << 1);
19     
20     return 0;
21 }
复制代码

 

参考资料

  AcWing 4207. 最长合法括号子序列(AcWing杯 - 周赛):https://www.acwing.com/video/3660/

posted @   onlyblues  阅读(1198)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
Web Analytics
点击右上角即可分享
微信分享提示