给定只包含括号字符'('和 ')''的字符串,请找出最长的有效括号内子括号的长度。举几个例子如下: 例如对于"( ()",最长的有效的括号中的子字符串是"()" ,有效双括号数1个,故它的长度为 2。 再比如对于字符串") () () )",其中最长的有效的括号中的子字符串是"() ()",有效双括号数2个,故它的长度为4。 再比如对于"( () () )",它的长度为6。
前一篇已经说了,直接匹配后虽然个人认为正确,但是交上去有误,虽然没有给出测试点,但是感觉应该是“有效括号”名词理解的问题,相信有很多小伙伴和我是同样的。根据小伙伴的提醒,确实需要连续。
如对字符串"()(()"的处理,按照最长括号的理解,有效括号是4个
但是,中间第三个"("却隔开了两个有效括号,真实答案为2个
事实证明,确实得按照连续考虑...(这一题只能交一次,所以开了个小号在英雄会上重新交了一次,问题解决)
动态规划:
下面说一下思想,既然已经了解题意是需要连续的有效括号的话,就不能按照之前那样伪入栈出栈来解决了,早上结合别人的帮助,自己解决了这个:
采用的是倒序匹配的方法,if(s[i] == '('),则继续进行匹配')',否则i--;继续向前匹配;
若继续匹配,通过int j = i + 1 + dp[i + 1]; 可以避免多余匹配,将之前有匹配的直接加上,然后匹配')';
匹配成功之后,修改dp[i]的值(这才是动态规划的实质);
再将 dp[i] += dp[j]; 即可得到最长有效,其中d[j]的值是我们有i匹配至j-1时,如果j也和前面连续的话,就可以进行有效叠加;
//核心代码:
for(int i = n - 2; i >= 0; i--) //倒序操作
{
if(s[i] == '(')
{
int j = i + 1 + dp[i + 1]; //避免多余匹配
if(s[j] == ')' && j < n)
{
dp[i] = dp[i + 1] + 2; //匹配,并改变此时的点到尾端的最长有效
if (j + 1 < n)
{
dp[i] += dp[j + 1]; //此时若是连续即可加上之前匹配,否则+0,即非连续
}
}
}
}
接下来直接找到dp中最大值即可,即是最长有效(因为dp[i] = dp[i + 1] + 2;故不用乘二)
下面贴出代码(加了很多输出是便于理解,大家可以试试):
#include <iostream>
#include <cstring>
using namespace std;
int longestValidParentheses(string s)
{
//动态规划
int sum = 0; //最长有效
int n = s.length();
int *dp = new int[n];
for(int i = 0; i < n; i++) //作为记录对应与s[i]的最长有效值
dp[i] = 0;
for(int i = n - 2; i >= 0; i--) //倒序操作
{
if(s[i] == '(')
{
int j = i + 1 + dp[i + 1]; //避免多余匹配
if(s[j] == ')' && j < n)
{
dp[i] = dp[i + 1] + 2; //匹配,并改变此时的点到尾端的最长有效
if (j + 1 < n)
{
dp[i] += dp[j + 1]; //此时若是连续即可加上之前匹配,否则+0,即非连续
}
}
}
}
for(int i = 0; i < n; i++) //找到最大值
{
cout<<dp[i]<<" "; //输出各个点的最长有效,顺序...
if(sum < dp[i])
sum = dp[i];
}
cout<<endl;
delete []dp;
return sum;
}
int main()
{
char s[] = "()(()";
int sum = longestValidParentheses (s);
for(int i = 0; s[i] != '\0'; i++) //找到最大值
{
cout<<s[i]<<" "; //输出各个点的最长有效,顺序...
}
cout<<endl;
cout<<"最长有效长度"<<sum<<endl;
return 0;
}
测试点:
如果有考虑不周到的,各位大牛提点一下,3Q...多多交流
本文探讨如何解决寻找字符串中最长有效括号子串的问题,通过动态规划的方法,采用倒序匹配策略,避免了由于非连续有效括号导致的错误。通过实例解释了算法思路,并给出了代码实现,最后邀请读者进行交流讨论。


被折叠的 条评论
为什么被折叠?



