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\n", dp[1][len]);//输出答案,记得换行
}
return 0;//结束
}

题解【POJ2955】Brackets的更多相关文章

  1. POJ2955 Brackets —— 区间DP

    题目链接:https://vjudge.net/problem/POJ-2955 Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Su ...

  2. POJ-2955 Brackets(括号匹配问题)

    题目链接:http://poj.org/problem?id=2955 这题要求求出一段括号序列的最大括号匹配数量 规则如下: the empty sequence is a regular brac ...

  3. poj2955:Brackets

    Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8716   Accepted: 4660 Descript ...

  4. poj2955 Brackets (区间dp)

    题目链接:http://poj.org/problem?id=2955 题意:给定字符串 求括号匹配最多时的子串长度. 区间dp,状态转移方程: dp[i][j]=max ( dp[i][j] , 2 ...

  5. 间隔DP基础 POJ2955——Brackets

    取血怒.first blood,第一区间DP,这样第一次没有以某种方式在不知不觉中下降~~~ 题目尽管是鸟语.但还是非常赤裸裸的告诉我们要求最大的括号匹配数.DP走起~ dp[i][j]表示区间[i, ...

  6. POJ2955 Brackets(区间DP)

    给一个括号序列,求有几个括号是匹配的. dp[i][j]表示序列[i,j]的匹配数 dp[i][j]=dp[i+1][j-1]+2(括号i和括号j匹配) dp[i][j]=max(dp[i][k]+d ...

  7. POJ2955 Brackets (区间DP)

    很好的区间DP题. 需要注意第一种情况不管是否匹配,都要枚举k来更新答案,比如: "()()()":dp[0][5]=dp[1][4]+2=4,枚举k,k=1时,dp[0][1]+ ...

  8. 各种DP总结

    一.数位DP 1.含有或不含某个数“xx”: HDU3555 Bomb HDU2089 不要62 2.满足某些条件,如能整除某个数,或者数位上保持某种特性: HDU3652 B-number Code ...

  9. [总结-动态规划]经典DP状态设定和转移方程

    马上区域赛,发现DP太弱,赶紧复习补上. #普通DP CodeForces-546D Soldier and Number Game 筛法+动态规划 待补 UVALive-8078 Bracket S ...

随机推荐

  1. meet in the middle 折半搜索 刷题记录

    复杂度分析 假设本来是n层,本来复杂度是O(2^n),如果meet in middle那就是n/2层,那复杂度变为O( 2^(n/2) ),跟原来的复杂度相比就相当于开了个方 比如如果n=40那爆搜2 ...

  2. idea 添加 开发者信息

    #if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end #parse( ...

  3. Nginx实现前端访问后端本地接口

    Nginx配置两个地方就行: 先是配置好自己项目的服务,确保自己的项目能运行: location / { root /web/xiangmu/public; // 本地项目的路径 index inde ...

  4. numpy 中array 和ndrray的区别联系

    numpy.array()  标明array只是一个方法 ndarray 是类名,是一个实例. a=numpy.array(b)    #这是把变量b转换为数组a,这里array()是个方法,a的类型 ...

  5. springboot整合websocket实现客户端与服务端通信

    定义  WebSocket是通过单个TCP连接提供全双工(双向通信)通信信道的计算机通信协议.此WebSocket API可在用户的浏览器和服务器之间进行双向通信.用户可以向服务器发送消息并接收事件驱 ...

  6. Codeforces Round #600 (Div. 2) C - Sweets Eating

    #include<iostream> #include<algorithm> #include<cstring> using namespace std ; typ ...

  7. 题解【洛谷P2070】刷墙

    题面 将每一次移动的距离进行差分,前缀和判断移动的距离是否\(\geq 2\)即可. #include <bits/stdc++.h> #define itn int #define gI ...

  8. OpenShift 4.3环境中创建基于Go的Operator

    详细步骤可以参考官方文档 https://docs.openshift.com/container-platform/4.3/operators/operator_sdk/osdk-getting-s ...

  9. selenium获取短暂出现元素的xpath路径

    1. pip install beautifulsoup4  :安装beautifulsoup4 2. from bs4 import BeautifulSoup 3. bs = BeautifulS ...

  10. jQuery func

    1.  $(selector).each(function(index,element)); -----------index 选择器的index位置,element --当前的元素 2. _.eac ...