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 [([])]
.
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.
For each input case, the program should print the length of the longest possible regular brackets subsequence on a single line.
((())) ()()() ([]]) )[)( ([][][) end
6 6 4 0 6
【题解】
题意:求能配对的括号弧的最长序列。
分析:
区间dp,设dp[i][j]为从第i到第 j 个括号的最长匹配长度,这题题简单,但是要特别注意初始化,比较坑,
首先初始化区间dp[i][i]为0,这很简单,然后要初始化dp[i][i+1],这里要判断,如果s[i]和s[i+1]是配对的,那么dp[i][i+1]就等于2了,否则就是0;
接下来,比如说有长度为6的序列,假如求dp[2][5],那区间2到5的最大长度就是区间2~3加上4~5,区间2~4加上5和区间2~5 三者中的最大值,就是2~5的最大值,当然,
这里要提前判断一下2和5是不是配对的,如果配对的话,那就是区间3~4的值加上2,否则就是上面的遍历过程,这只是一个区间,其他区间都是如此,所以转移方程就是:
如果i,j不配对:
dp[i][j]=max(dp[i][j], dp[i][k]+dp[k+1][j]);
如果配对:
dp[i][j]=dp[i+1][j-1]+2;
因为初始化问题哇了好几发呢,,要千万注意!!
【AC代码】
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=200;
int dp[N][N];
int m,n;
char s[N];int judge(char a,char b)
{if(a=='['&&b==']') return 1;if(a=='('&&b==')') return 1;return 0;
}int main()
{while(~scanf("%s",s)&&s[0]!='e'){int len=strlen(s);for(int i=0;i<len;++i)//预处理{dp[i][i]=0;if(judge(s[i],s[i+1]))dp[i][i+1]=2;elsedp[i][i+1]=0;}for(int i=3;i<=len;++i){for(int j=0;j+i-1<len;++j){int k=i+j-1;dp[j][k]=0;if(judge(s[j],s[k]))//配对的话dp[j][k]=dp[j+1][k-1]+2;for(int l=j;l<k;++l)//不配对的话{dp[j][k]=max(dp[j][k],dp[j][l]+dp[l+1][k]);}}}printf("%d\n",dp[0][len-1]);}return 0;
}