Brackets
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 6622 | Accepted: 3558 |
Description
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
Source
题目大意:给你一个长度不超过100的括号序列,求最长合法括号子序列的长度。合法的括号序列满足下列条件:
1.空的括号序列是合法的;
2.如果一个括号序列s是合法的,那么(s)和[s]都是合法的;
3.如果两个括号序列a和b都是合法的,那么ab也是合法的;
4.其他的括号序列都是不合法的。
例如:(), [], (()), ()[], ()[()]都是合法的,而(, ], )(, ([)], ([(]都是不合法的。
解题思路:一道典型的区间DP模型题目。分析一下问题,可以发现:如果找到一对匹配的括号,例如[xxx]oooo,就把区间分成两部分,一部分是xxx,另一部分是oooo。
设dp[i][j]表示区间[i,j]之间的最长合法括号子序列的长度,那么当i<j时,如果区间[i+1,j]内没有与i匹配的括号,则dp[i][j]=dp[i+1][j];如果存在一个与之匹配的k,那么dp[i][j]=max{dp[i+1][j], dp[i+1][k-1]+dp[k+1][j]+1(i<=k<=j&&i和k是一对匹配的括号)}。因此,我们将整个串长作为区间进行搜索,那么最后2*dp[0][len-1]即为答案,len表示串的长度。详见代码。
附上AC代码:
1 #include <cstdio> 2 #include <cstring> 3 using namespace std; 4 const int maxn = 105; 5 char str[maxn]; 6 int dp[maxn][maxn]; 7 8 bool match(char a, char b){ 9 return (a==‘(‘&&b==‘)‘) || (a==‘[‘&&b==‘]‘); 10 } 11 12 int dfs(int l, int r){ 13 if (l >= r) 14 return 0; 15 if (l+1 == r) 16 return dp[l][r] = match(str[l], str[r]); 17 if (dp[l][r]) 18 return dp[l][r]; 19 int ans = dfs(l+1, r); 20 for (int i=l; i<=r; ++i) 21 if (match(str[l], str[i])){ 22 int t = dfs(l+1, i-1)+dfs(i+1, r)+1; 23 if (t > ans) 24 ans = t; 25 } 26 return dp[l][r] = ans; 27 } 28 29 int main(){ 30 while (~scanf("%s", str) && str[0]!=‘e‘){ 31 memset(dp, 0, sizeof(dp)); 32 int len = strlen(str); 33 dfs(0, len-1); 34 printf("%d\n", 2*dp[0][len-1]); 35 } 36 return 0; 37 }