题意:
给一个只包含 ′ ( ′ 、 ′ ) ′ '('、')' ′(′、′)′左右括号的字符串,询问最长的合法括号序列的长度和出现次数。
题解:
设
d
p
[
i
]
dp[i]
dp[i]表示以位置为
i
i
i的右括号结尾的最长合法括号子序列的长度,状态转移方程可以得出是:
d
p
[
i
]
=
d
p
[
c
u
r
−
1
]
+
i
−
c
u
r
+
1
dp[i] = dp[cur - 1]+i-cur+1
dp[i]=dp[cur−1]+i−cur+1,其中,
c
u
r
cur
cur表示位置为
i
i
i的右括号所对应的左括号的位置,这个可以使用栈记录,也就是对应的栈顶元素。
这道题目也可以贪心做。括号问题经常用到栈。
实现细节见代码:
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int MAXN = 1e6 + 10;
const int mod = 1e9 + 7;
stack<int> st;
int dp[MAXN];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
string s;
cin >> s;
int sum = 0;
int maxx = 0;
for (int i = 0; s[i]; i++) {
if (s[i] == '(') {
st.push(i);
}
else {
if (!st.empty()) {
int cur = st.top();
st.pop();
dp[i] = dp[cur - 1] + i - cur + 1;
if (dp[i] > maxx) {
maxx = dp[i];
sum = 1;
}
else if (dp[i] == maxx) {
sum++; // 记录最长串出现次数
}
}
}
}
if (maxx) {
cout << maxx << " " << sum << endl;
}
else {
cout << "0 1" << endl;
}
return 0;
}