题目链接:POJ 2955
We give the following inductive definition of a “regular brackets” sequence:
- the empty sequence is a regular brackets sequence,
- if s is a regular brackets sequence, then (s) and [s] are regular brackets sequences, and
- if a and b are regular brackets sequences, then ab is a regular brackets sequence.
- no other sequence is a regular brackets sequence
For instance, all of the following character sequences are regular brackets sequences:
(), [], (()), ()[], ()[()]
while the following character sequences are not:
(, ], )(, ([)], ([(]
Given a brackets sequence of characters a1a2 … an, your goal is to find the length of the longest regular brackets sequence that is a subsequence of s. That is, you wish to find the largest m such that for indices i1, i2, …, im where 1 ≤ i1 < i2 < … < im ≤ n, ai1ai2 … aim is a regular brackets sequence.
Given the initial sequence ([([]])]
, the longest regular brackets subsequence is [([])]
.
Input
The input test file will contain multiple test cases. Each input test case consists of a single line containing only the characters (
, )
, [
, and ]
; each input test will have length between 1 and 100, inclusive. The end-of-file is marked by a line containing the word “end” and should not be processed.
Output
For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line.
Sample Input
((()))
()()()
([]])
)[)(
([][][)
end
Sample Output
6
6
4
0
6
题意:一个串中含有‘ ( ’, ‘ ) ’, ‘ [ ’, ‘ ] ’ 四种字符, 两种括号对"()", "[]"可以计数, 括号对两边同时加上同一种左右括号也可以计数, 即:(()), [()]。要求输出一个串中可以计数的字符长度。
题解 :这个题用区间DP来求解, 仍用DP[i][j]来存i 到j 的最大匹配值, 寻找最优切割点dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j])也是中规中矩的, 只不过某种情况下DP[i][j]会因为i 和 j 的位置存在括号匹配的情况增加, 比如"(())", 但有时两边的括号已经跟别的括号匹配了, 比如“()()", 这种情况下就需要一个另外的判断式子dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + 1), 用来处理这种情况。
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int i, j, n, ans, len, k;
int dp[105][105] = {0};
char str[105];
while(scanf("%s", str) && str[0] != 'e'){
for(len = 2;len <= strlen(str);len++){//区间长度
for(i = 0;i < strlen(str);i++){//枚举起点i
j = i + len - 1;//计算终点j
if(j >= strlen(str))//越界跳出
break;
for(k = i;k <= j;k++)
dp[i][j] = max(dp[i][j], dp[i][k] + dp[k + 1][j]);//递推关系, 通过小区间计算得出大区间的值
if(str[i] == '(' && str[j] == ')' || str[i] == '[' && str[j] == ']')
dp[i][j] = max(dp[i][j], dp[i + 1][j - 1] + 1);//处理特殊情况
}
}
printf("%d\n", dp[0][strlen(str) - 1] * 2);
memset(dp, 0, sizeof(dp));
memset(str, 0, sizeof(str));
}
return 0;
}