读取括号
题目链接https://www.starrycoding.com/problem/423
动态规划解法
题意可以简化为将这一串括号从前往后分成合法括号组 求最小的组数
此题等价于最长括号匹配
设f[i]:从i位置开始的最长合法括号匹配长度
当前后括号匹配时,即
s[i] == '(' && s[i + f[i + 1] + 1] == ')'
有转移方程
f[i] = f[i + 1] + 2 + f[f[i + 1] + i + 2]
这样写有点难看 可以写成
f[i] = f[i + 1] + 2, f[i] += f[i + f[i]]
可以理解为两括号匹配,最大长度增加2
同时还要合并在f[i] + i之后的合法括号组的长度
求出f[i]后,再求一次dp
设dp[i]:从i位置开始到末尾最少可以分成多少组
有转移方程
dp[i] = dp[i + max(f[i] + 1)] + 1
代码如下
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
int main () {
ios::sync_with_stdio(0), cin.tie(0);
int n;cin >> n;
string s;cin >> s;
s = " " + s;
vector<int> S;
// f[i]:从i位置开始能读取的最多合法括号序列
vector<int> f(n + 2);
for (int i = n;i >= 1; -- i) {
if (s[i] == ')') ;
else {
if (s[i] == '(' && s[i + f[i + 1] + 1] == ')') {
f[i] = f[i + 1] + 2;
f[i] += f[i + f[i]];
}
}
}
// dp[i]:从i位置读取到末尾需要的次数
vector<int> dp(n + 2);
for (int i = n;i >= 1; -- i) {
dp[i] = dp[i + max(f[i], 1)] + 1;
}
cout << dp[1] << '\n';
return 0;
}

浙公网安备 33010602011771号