POJ2955-Brackets(区间dp 括号匹配)

本文探讨了如何寻找给定字符串中最长的正确匹配括号子序列的问题,通过动态规划方法,详细解释了如何构建解决方案,包括状态转移方程和边界条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

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 a1a2an, 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 < … < imn, ai1ai2aim 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[ i ] [ j ] 是字符串i 到 j 的括号匹配的最大长度,从子情况得到父情况主要有两种。

① ( ... ) [ ... ] 型,即左右分开,合起来是dp[ i ] [ j ],用k循环 求所有的最大值 ;

② ( ....  ) 型,即最左和最后是匹配的,中间的情况加一是dp[ i ] [ j ] .

所有情况比较,求最大值,就是dp[ i ] [ j ].


#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;

int dp[110][110];
char str[110];

int main()
{
    while(~scanf("%s",str+1))
    {
        if(str[1]=='e') break;
        memset(dp,0,sizeof(dp));

        int len = strlen(str+1);
        for(int l=1;l<=len;l++){
            for(int i=1;i<=len;i++){
                int j = i+l-1;
                if(j>len) continue;
                if((str[i]=='('&&str[j]==')')||(str[i]=='['&&str[j]==']') )
                    dp[i][j] = dp[i+1][j-1] + 2;
                    //dp[i+1][j-1],当i+1>j-1,值仍为0
                for(int k=1;k<=j;k++)
                    dp[i][j] = max(dp[i][j],dp[i][k]+dp[k+1][j]);
            }
        }
        printf("%d\n",dp[1][len]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值