// TOPCODER SAM 686 div1 300
Problem Statement
带有小中括号的括号序列,问可以去掉多少子串,使得剩下的非空串是合法的。
Constraints
字符串长度不超过 40。
Examples
// ans[i] = count(s[i])
string s[] = {"()[]", "())", "()()", "([)]", "())[]][]([]()]]()]]]"};
int ans[] = {3, 2, 4, 2, 3854};
Solution
寻找反面,等价于有多少非空的子串是合法的。这是一个区间 dp,不难转移。
Code
- #include <string.h>
-
- #include <string>
-
- const int N = 123;
-
- class BracketSequenceDiv1
- {
- int n;
- char str[N];
- long long dp[N][N];
-
- public:
- long long count(std::string std_str)
- {
- n = std_str.size();
- for (int i = 1; i <= n; ++i) {
- str[i] = std_str[i-1];
- }
- memset(dp, 0, sizeof(dp));
- return count(n);
- }
-
- long long count(int n)
- {
- for (int d = 1; d <= n; ++d) {
- for (int i = 1; i + d - 1 <= n; ++i) {
- int j = i + d - 1;
- dp[i][j] = dp[i][j-1];
- if (str[j] == ‘)‘) {
- for (int k = i; k < j; ++k) {
- // dp[i k-1] ( dp[k+1, j-1] )
- if (str[k] == ‘(‘) {
- dp[i][j] += (dp[i][k-1] + 1) * (dp[k+1][j-1] + 1);
- }
- }
- }
- else if (str[j] == ‘]‘) {
- for (int k = i; k < j; ++k) {
- // dp[i, k-1] [ dp[k+1, j-1] ]
- if (str[k] == ‘[‘) {
- dp[i][j] += (dp[i][k-1] + 1) * (dp[k+1][j-1] + 1);
- }
- }
- }
- }
- }
- return dp[1][n];
- }
- };
时间: 2024-10-06 04:03:57