zoukankan      html  css  js  c++  java
  • 题解【POJ2955】Brackets

    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 (a_{1}a_{2} … a_{n}), 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 (i_{1}, i_{2}, …, i_{m}) where (1 ≤ i_{1} < i_{2} < … < i_{m} ≤ n, a_{i1}a_{i2} … a_{im}) 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

    Stanford Local 2004

    Solution

    题意简述:给出一个的只有'(',')','[',']'四种括号组成的字符串,求最多有多少个括号满足题目里所描述的完全匹配。

    本题考察了区间DP,可以称为是区间DP的模板题。

    区间DP的板子(来源:https://blog.csdn.net/qq_40772692/article/details/80183248):

    for (int len = 1; len <= n; len++)//枚举长度
    {
        for (int j = 1; j + len <= n + 1; j++)//枚举起点,ends<=n
        {
            int ends = j + len - 1;
            for (int i = j; i < ends; i++)//枚举分割点,更新小区间最优解
            {
                dp[j][ends] = min(dp[j][ends], dp[j][i] + dp[i + 1][ends] + something);
            }
        }
    }
    

    (dp[i][j])为区间(i)~(j)中最长合法序列的长度。

    首先,可以直接判断输入的字符串的第(i)位和第(j)位是否匹配,如果能成功匹配,就更新(dp[i][j] = dp[i + 1][j - 1] + 2)

    在这个基础上,枚举分割点(k),更新小区间内的最优解。

    为了方便存储,我们将字符串整体向右移动(1)位。

    最后输出(dp[1][字符串长度])即可。

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <cctype>
    
    using namespace std;
    
    inline int gi()
    {
        int f = 1, x = 0; char c = getchar();
        while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar();}
        while (c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar();}
        return f * x;
    }
    
    char s[103];
    int dp[103][103];
    
    int main()
    {
    	while (scanf("%s", s + 1) != EOF)//将输入的字符串整体右移1位
    	{
    		memset(dp, 0, sizeof(dp));//dp数组清零
    		int len = strlen(s + 1);//字符串长度
    		if (s[1] == 'e') return 0;//输入结束
                     /*开始区间DP*/
    		for (int i = 1; i <= len; i++)//枚举长度
    		{
    			for (int j = 1; j + i <= len + 1; j++)//枚举起点
    			{
    				int k = j + i - 1;//终点
    				if ((s[j] == '(' && s[k] == ')') || (s[j] == '[' && s[k] == ']')) //如果s[i]和s[j]相匹配
    				{
    					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
    ", dp[1][len]);//输出答案,记得换行
    	}
    	return 0;//结束
    }
    
  • 相关阅读:
    twitter分享问题(三)——Required oauth_verifier parameter not provided
    旋转数组的最小数字
    关系型数据库基础之:简单的数据查询
    twitter分享问题(一)——MISSING_ARG_APIKEY
    extern "C"的理解
    从一个链接错误探究GCC的链接库顺序
    GAE 博客——B3log Solo 0.4.0 正式版发布了!
    不使用资源文件动态创建对话框的做法
    GAE 博客——B3log Solo 0.4.0 正式版发布了!
    CodeBlocks启动多个进程实例的做法
  • 原文地址:https://www.cnblogs.com/xsl19/p/11125136.html
Copyright © 2011-2022 走看看