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;//结束
    }
    
  • 相关阅读:
    js 多物体运动
    js运动 淡入淡出
    js运动 分享到
    正则 重复项最多得子项
    jq 拖拽
    jq 弹出窗口
    jq 选项卡
    jq 写法
    Codeforces 185A Plant( 递推关系 + 矩阵快速幂 )
    HDU 2604 Queuing( 递推关系 + 矩阵快速幂 )
  • 原文地址:https://www.cnblogs.com/xsl19/p/11125136.html
Copyright © 2011-2022 走看看