POJ 2955 Brackets (区间dp,匹配括号数)

题意

合法括号:
(), [], (()), ()[], ()[()]
非法括号:
(, ], )(, ([)], ([(]
合法括号+合法括号还是合法。合法括号套合法括号也是合法。
给定一个仅由’(‘,’)’,’[‘,’]’组成的字符串。求最长合法括号子序列。

解题

一开始想着用栈去操作,将‘(‘,’[‘入栈,然后遇到‘)’,’]’时出栈去匹配。但是因为’([)] ‘是非法括号,所以此解法不行。
因为要记录区间[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;
}

猜你喜欢

转载自blog.csdn.net/qq_37685156/article/details/81158450
今日推荐