题解#2
2026-09-18 21:22:07
发布于:湖南
6阅读
0回复
0点赞
分析
问题:统计字符串(只含 ( 和 ) )的所有子序列中,合法括号序列的数量(含空串),答案对取模。。
关键观察:一个子序列是合法括号序列,当且仅当:
1.
长度是偶数
2.
前个字符全是 ( ,后个全是 )
DP 设计:设表示考虑前个字符,当前已选子序列中有个未匹配的 ( 的方案数。
不选 :
选 :
若(多了一个未匹配左括号)
若(匹配掉一个左括号)
最终答案为(所有左括号都被匹配)。
验证:
空串:1 种
() :选位置或,共 2 种
总计 3
复杂度:,完全可行。
代码:
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9;
const int MAXN = 2005;
int n;
char s[MAXN];
long long f[2][MAXN]; // 滚动数组
int main() {
scanf("%d", &n);
scanf("%s", s + 1);
f[0][0] = 1;
for (int i = 1; i <= n; i++) {
int cur = i & 1, pre = cur ^ 1;
for (int j = 0; j <= n; j++) f[cur][j] = 0;
for (int j = 0; j <= i; j++) {
// 不选 s[i]
f[cur][j] = (f[cur][j] + f[pre][j]) % MOD;
// 选 s[i]
if (s[i] == '(') {
if (j >= 1) f[cur][j] = (f[cur][j] + f[pre][j - 1]) % MOD;
} else {
if (j + 1 <= i) f[cur][j] = (f[cur][j] + f[pre][j + 1]) % MOD;
}
}
}
printf("%lld\n", f[n & 1][0]);
return 0;
}
验证:
样例1:,答案
样例2:34 个字符,17 个 ( 后 17 个 ) ,答案(可用代码验证)
说明:
中最大为(前个字符最多选个左括号),内层循环到即可
用滚动数组将空间从降到
答案包含空串(的转移路径)
这里空空如也





有帮助,赞一个