题意
合法括号:
(), [], (()), ()[], ()[()]
非法括号:
(, ], )(, ([)], ([(]
合法括号+合法括号还是合法。合法括号套合法括号也是合法。
给定一个仅由’(‘,’)’,’[‘,’]’组成的字符串。求最长合法括号子序列。
解题
一开始想着用栈去操作,将‘(‘,’[‘入栈,然后遇到‘)’,’]’时出栈去匹配。但是因为’([)] ‘是非法括号,所以此解法不行。
因为要记录区间[x,y]的最长合法括号子序列长度,所以不妨直接设dp[i][j]表示区间[i,j]的最长合法括号子序列长度。
根据合法括号的定义:合法+合法与合法套合法。
状态转移方程如下:
dp[i][j]=max{dp[i][k]+dp[k+1][j],dp[i+1][j-1]+a[i]匹配a[j]}。
其中a[i]表示字符串第i个字符。
AC代码
//32ms
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <stack>
using namespace std;const int maxn=120;
int dp[maxn][maxn];int main()
{string s;while(cin>>s){if(s=="end") break;int n=s.size();memset(dp,0,sizeof(dp));for(int l=1;l<=n;l++){for(int i=0;i+l-1<n;i++){int j=i+l-1;if((s[i]=='('&&s[j]==')') || (s[i]=='['&&s[j]==']')){dp[i][j]=dp[i+1][j-1]+2;}for(int k=i;k<j;k++){dp[i][j]=max(dp[i][j],dp[i][k]+dp[k+1][j]);}}}cout<<dp[0][n-1]<<endl;}return 0;
}