最长括号匹配 1944洛谷

最长括号匹配

算法:使用dp
注意:数组直接用dp[1000000]会超过范围应该使用malloc
转载地址
设 d p [ i ] dp[i]dp[i] 表示以 s [ i ] s[i]s[i] 结尾的最长括号匹配长度
显然当 s [ i ] s[i]s[i] 为左括号时 d p [ i ] = 0 dp[i]=0dp[i]=0
当 s [ i ] s[i]s[i] 为右括号时,d p [ i ] dp[i]dp[i] 一定与 d p [ i − 1 ] dp[i-1]dp[i−1] 有关
容易发现 s [ i − d p [ i − 1 ] ] s[i-dp[i-1]]s[i−dp[i−1]] 是 d p [ i − 1 ] dp[i-1]dp[i−1] 的起始字符
则当 s [ i − d p [ i − 1 ] − 1 ] s[i-dp[i-1]-1]s[i−dp[i−1]−1] 与 s [ i ] s[i]s[i] 合法匹配时,有
d p [ i ] = d p [ i − 1 ] + 2 + d p [ i − d p [ i − 1 ] − 2 ] dp[i]=dp[i-1]+2+dp[i-dp[i-1]-2]dp[i]=dp[i−1]+2+dp[i−dp[i−1]−2]
这里的 d p [ i − d p [ i − 1 ] − 2 ] dp[i-dp[i-1]-2]dp[i−dp[i−1]−2] 只需要一个例子就好理解了

123456
1
2
假设此时为 d p [ 5 ] = 2 dp[5]=2dp[5]=2 ,对于以 s [ 5 ] s[5]s[5] 结尾的最长括号匹配显然是[]
然后到了 d p [ 6 ] = 6 dp[6]=6dp[6]=6 ,注意到此时 s [ 3 ] s[3]s[3] 被合法利用了,
这样就造成了 s [ 3 ] s[3]s[3] 之前的 d p [ 6 − d p [ 5 ] − 2 ] = d p [ 2 ] dp[6-dp[5]-2] = dp[2]dp[6−dp[5]−2]=dp[2] 被重新利用

应该很好理解了
————————————————
版权声明:本文为优快云博主「q779」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_50332374/article/details/124792289

#include <iostream>
#include <string>
using namespace std;

int main() {
	int Max = 0;
	int p = -1;
	string ch;
	int *dp = (int *)malloc(1000000 * sizeof(int));
	getline(cin, ch);
	int len = ch.size();
	for (int i = 0; i < len; ++i) {
		if (ch[i] == '(' || ch[i] == '[') {
			dp[i] = 0;
			continue;
		} else {
			if ((ch[i - dp[i - 1] - 1] == '(' && ch[i] == ')' ) || (ch[i - dp[i - 1] - 1] == '[' && ch[i] == ']') ) {
				dp[i]
				    = dp[i - 1] + 2;
				if (i >= 2) {
					dp[i] += dp[i - dp[i - 1] - 2];
				}
				if (dp[i] > Max) {
					Max = dp[i];
					p = i;
				}
			}
		}

	}
	for (int i = p - dp[p] + 1; i <= p; ++i) {
		cout << ch[i];
	}
	cout << endl;
	return 0;
}
### 回答1: 使用动态规划解决最长括号匹配问题的代码如下:int lengthOfLongestValidParentheses(string s) { int n = s.length(), maxLen = 0; vector<int> dp(n, 0); for (int i = 1; i < n; i++) { if (s[i] == ')') { if (s[i - 1] == '(') { dp[i] = (i - 2 >= 0 ? dp[i - 2] : 0) + 2; } else if (i - dp[i - 1] - 1 >= 0 && s[i - dp[i - 1] - 1] == '(') { dp[i] = dp[i - 1] + 2 + ((i - dp[i - 1] - 2 >= 0) ? dp[i - dp[i - 1] - 2] : 0); } maxLen = max(maxLen, dp[i]); } } return maxLen; } ### 回答2: 以下是用动态规划算法最长括号匹配问题的代码: ```python def longest_valid_parentheses(s: str) -> int: n = len(s) if n == 0: return 0 dp = [0] * n ans = 0 for i in range(1, n): if s[i] == ')': if s[i - 1] == '(': if i >= 2: dp[i] = dp[i - 2] + 2 else: dp[i] = 2 elif i - dp[i - 1] > 0 and s[i - dp[i - 1] - 1] == '(': if i - dp[i - 1] >= 2: dp[i] = dp[i - 1] + dp[i - dp[i - 1] - 2] + 2 else: dp[i] = dp[i - 1] + 2 ans = max(ans, dp[i]) return ans ``` 该算法使用动态规划来求解最长括号匹配问题。定义一个长度为n的dp数组,其中dp[i]表示以下标为i的字符结尾的最长有效括号子串的长度。遍历字符串s,当遇到'('时,不需要做任何计算;当遇到')'时,分为两种情况:如果前一个字符是'(',则dp[i] = dp[i-2] + 2;如果前一个字符是')',则需要判断前一个字符所对应的最长有效括号子串的前一个字符是否是'(',如果是,则dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2。最后,取dp数组中的最大值即为最终的结果。算法的时间复杂度为O(n),空间复杂度为O(n)。 ### 回答3: 最长括号匹配问题可以使用动态规划算法来解决,具体代码如下: ```python def longestValidParentheses(s): n = len(s) if n < 2: return 0 dp = [0] * n # dp[i]表示以s[i]为结尾的最长括号长度 max_length = 0 for i in range(1, n): if s[i] == ')': if s[i-1] == '(': # 形如 "()" 的匹配 dp[i] = dp[i-2] + 2 if i >= 2 else 2 elif i - dp[i-1] > 0 and s[i - dp[i-1] - 1] == '(': # 形如 "))" dp[i] = dp[i-1] + dp[i - dp[i-1] - 2] + 2 if i - dp[i-1] >= 2 else dp[i-1] + 2 max_length = max(max_length, dp[i]) return max_length ``` 原理解释: 动态规划的思路是从左到右遍历字符串,维护一个dp数组来记录以当前字符为结尾的最长括号长度。 在遍历过程中,我们需要处理两种情况: 1. 形如 "()" 的匹配:如果当前字符是")",且前一个字符是"(",则可以形成一个有效的括号匹配,这时dp[i]的值可以由dp[i-2] + 2得到,也即前一个最长括号长度再加上当前匹配的长度2。 2. 形如 "))" - 如果当前字符是")",且前一个字符也是")",我们需要判断前一个最长括号匹配的前一个字符是否是"(",如果是,则可以形成一个有效的括号匹配,并且dp[i]的值可以由前一次最长括号长度dp[i-1]再加上到前一个有效括号匹配的前一个位置的最长括号长度dp[i - dp[i-1] - 2],再加上当前匹配的长度2得到。此时需要特别注意边界情况,即当i - dp[i-1] < 2时,没有前一个有效的括号匹配,所以直接加上当前匹配的长度2即可。 遍历结束后,返回dp数组的最大值,即为最长括号匹配的长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值