括号匹配问题


简单括号匹配问题是给出字符串,判断字符串中的括号是否匹配,此类问题核心解决方案就是利用栈的后进先出的特性,从左到右依次遍历字符串,遇左括号进栈,遇右括号将其与栈顶元素配对,若能配对,则栈顶元素出栈,继续遍历,若不能配对,则返回false。字符串遍历结束后,判断栈是否为空,若不为空返回false,若为空,返回true。以下有c和c++实现代码,用c++可以利用标准库提供的顺序容器适配器stack来实现栈结构,c语言则需要自己写栈结构,当然也可以用数组模拟栈结构,用一变量存放数组中最后面的元素的下标代表栈顶指针进行入栈出栈就可以了。

c语言版 题目来自http://nyoj.top/problem/2

 /*
现在有一行括号序列,请你检查这行括号是否配对
输入
第一行输入一个数N(0<N<=100),表示有N组测试数据。后面的N行输入多组输入数据,
每组输入数据都是一个字符串S(S的长度小于10000,且S不是空串),测试数据组数少于5组。
数据保证S中只含有"[", "]", "(", ")" 四种字符
输出
每组输入数据的输出占一行,如果该字符串中所含的括号是配对的,则输出Yes,如果不配对则输出No
实现:
栈模型实现
*/
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h> typedef struct Node * PNODE; struct Node
{
char data;
PNODE pNext;
}NODE; typedef struct Stack
{
PNODE pTop; //永远指向栈顶元素
PNODE pBottom; //永远指向栈顶元素的下一个元素
}STACK,* PSTACK; /* 建立空栈 */
void InitStack(PSTACK pS)
{
pS->pTop = (PNODE)malloc(sizeof(NODE)); //头节点
pS->pBottom = pS->pTop;
pS->pTop->pNext = NULL; //将头节点指针域变成空的
} /* 进行压栈 */
void PushStack(PSTACK pS,char Str)
{
PNODE pNew = (PNODE)malloc(sizeof(NODE));//建立新节点
pNew->data = Str; //存储数据
pNew->pNext = pS->pTop; //将新节点进行压栈,头进头出
pS->pTop = pNew; //将头节点指向新节点
}
/* 进行出栈 */
char PopStack(PSTACK pS)
{
PNODE p = pS->pTop; //缓存出栈的节点地址
char str = p->data; //缓存出栈的节点数据 pS->pTop = p->pNext;//将栈顶往后移
free(p);//将出栈节点销毁
return str; //将出栈节点数据返回
}
/* 判断栈是否为空*/
bool empty(PSTACK pS)
{
if(pS->pTop == pS->pBottom)
return true;
else
return false;
} /* 扫描字符串 */
bool scanner(char * pStr)
{
STACK S;
int i = ;
bool ret = true; InitStack(&S);
while(*(pStr+i) != '\0')
{
switch(*(pStr+i))
{
case '(':
PushStack(&S,*(pStr+i));
break;
case '[':
PushStack(&S,*(pStr+i));
break;
case ')':
if(empty(&S))//如果栈已为空
{
return false;
}
ret = (PopStack(&S) == '(');
if(ret == false)
{
return ret;
}
break;
case ']':
if(empty(&S))
{
return false;
}
ret = (PopStack(&S) == '[');
if(ret == false)
{
return ret;
}
break;
}
i++;
}
if(empty(&S) == false) //如果扫描完字符串栈不是空的
{
ret = false;
}
return ret; } int main(void)
{
int n,ret;
char str[];
scanf("%d",&n);
getchar();
while(n--)
{
scanf("%s",str);
getchar();
if(scanner(str))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
} return ;
}

c语言实现

c++版 题目来自http://codevs.cn/problem/2058/

 /*括号配对*/
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int main(void)
{
stack<char> my_stack;
int n;
cin >> n; while(n--){
while( !my_stack.empty() ) //清空栈
my_stack.pop();
string t_str;
int k = ;
string::iterator begin,end; cin >> t_str;
begin = t_str.begin();
end = t_str.end();
while(begin != end){
char t = *begin++;
if(t == '<' || t == '(' || t == '{' || t == '[')
my_stack.push(t);
else{
if(my_stack.empty()){
cout << "FALSE" << endl;
k = ;
break;
}
char tch = my_stack.top();
if(t == '>' && tch != '<' ||
t == '}' && tch != '{' ||
t == ')' && tch != '(' ||
t == ']' && tch != '['){
cout << "FALSE" << endl;
k = ;
break;
}
my_stack.pop();
}
}
if(k){
if(my_stack.size())
cout << "FALSE" << endl;
else
cout << "TRUE" <<endl;
}
} return ;
}

c++实现

括号序列问题


此类问题给出一串由'(' ')' '[' ']' 四种字符组成的字符串,要求在字符串中添加若干个括号,使整个字符串达到匹配状态,这类问题属于区间动态规划问题,试想,题目要求的是整个字符串匹配的时候的最小的添加的括号的个数,我们定义两个指针变量i,j 分别指向字符串的头和尾,如果s[i]和s[j]匹配,那整个问题的解就是除了s[i]和s[j]后的子串s[i+1]到s[j-1]的解(代码第33行),而子串的解又由更小的字串的解来确定,所以可以知道,此问题采用自底而上的解法,亦或者说成自小而大的解法。上面的过程也可称为问题的状态转移过程,在考虑完状态转移过程后还必须考虑边界问题,状态转移是由小串到大串,所以从右至左或从左至右都可以,但是要考虑边界问题,此问题中,边界问题就是只有一个字符的字串和空串,用i和j代表一前一后两个字符,那么只有一个字符时也就是i和j相等时候,此时,dp[i][j],也就是dp[i][i]为1,当字串为空串时,也是i>j时候 此时 dp[i][j]为0 也可作dp[i+1][i]为0.由此想来,得是从右至左处理字符串方便。在程序中,需要将每个子串的最优解存起来,所以有数组dp[i][j]存储 从i到j的这个字串的最优解是多少。

题目自 http://nyoj.top/problem/15

#include<bits/stdc++.h>
using namespace std; int d[][]; bool match(char a, char b) {
// i肯定在j前面,所以a肯定得是左括号,b肯定得是右括号
return (a == '(' && b == ')' ) ||
(a == '[' && b == ']');
} int main(void)
{
int N;
cin >> N;
getchar();
while(N--) {
string s;
getline(cin, s);
int len = s.size();
if( len == ) {
cout << << endl;
continue;
}
memset(d,,sizeof(d));
for(int i = ; i < len; ++i) {
d[i][i] = ;
} for( int i = len -; i >= ; --i ) {
for( int j = i + ; j < len; ++j ) {
d[i][j] = 0x3f3f3f3f; // 0x3f3f3f3f 代表无穷大,有意研究者可自行百度
if(match(s[i],s[j])) d[i][j] = d[i+][j-];
for( int k = i; k < j; ++k ) {
d[i][j] = min(d[i][j],d[i][k]+d[k+][j]);
}
}
} cout << d[][len-] << endl;
} return ;
}

代码实现


总结

动态规划作为一种解决问题的思想,其主要手段就是存储子问题的最优解来导出整个问题的最优解,那么需要考虑的就是最小的子问题如果处置,也就是边界问题,还有就是子问题如何向整个问题迈进或者整个问题如何分成子问题来求解,如何利用子问题的解,和选择最优解,也就是状态转移问题。


 长袍纸扇山羊须,凉菜花生小酒,岂不美哉!

DP_括号匹配序列问题的更多相关文章

  1. [ZPG TEST 114] 括号匹配【树分治 点分治 括号序列】

    1.      括号匹配   有一棵树,每个节点上都有一个括号(左括号或者右括号).有多少个有序点对(u, v)从u到v的路径上的节点构成的字符串是一个合法的括号匹配?(我们称这样的点对是合法的) 输 ...

  2. [NYOJ 15] 括号匹配(二)

    括号匹配(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:6   描述 给你一个字符串,里面只包含"(",")","[&qu ...

  3. poj 2955 Brackets (区间dp 括号匹配)

    Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...

  4. NYOJ15|括号匹配(二)|区间DP|Elena

    括号匹配(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:6   描述 给你一个字符串,里面只包含"(",")","[&qu ...

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

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

  6. 括号匹配性检测C语言实现

    #include <stdio.h> #define SIMPLE_KUOHAO "(()1231qeqw)(@#$)" #define COMPLEX_KUOHAO ...

  7. 2016湖南省赛----G - Parenthesis (括号匹配)

    2016湖南省赛----G - Parenthesis (括号匹配)   Bobo has a balanced parenthesis sequence P=p 1 p 2…p n of lengt ...

  8. ACM_括号匹配

    括号匹配(栈) Time Limit: 2000/1000ms (Java/Others) Problem Description: 给一组包含[]()两种括号的序列,检查是否是合法的. 如:()[] ...

  9. CodeForces - 5C(思维+括号匹配)

    题意 https://vjudge.net/problem/CodeForces-5C 给出一个括号序列,求出最长合法子串和它的数量. 合法的定义:这个序列中左右括号匹配. 思路 这个题和普通的括号匹 ...

随机推荐

  1. MySQL -Naivacat工具与pymysql模块

    Navicat 在生产环境中操作MySQL数据库还是推荐使用命令行工具mysql,但在我们自己开发测试时,可以使用可视化工具Navicat,以图形界面的形式操作MySQL数据库. 官网下载:https ...

  2. 寒假关于计算机课程的学习计划(第二次作业<二>)

    由于自己刚从紧张的高中学习中解脱出来,进入大学学习意识不够重视,导致学业与别人相差较大,特别是C语言,所以打算寒假主要先补一补C语言.自己在网上查找了很多资料,包括浙江大学翁凯老师在网易云课堂讲的&l ...

  3. JavaScript设计模式导学

    如何成为一名合格的工程师? 作为一名合格的工程师,不仅需要懂代码,还要懂设计,一名合格工程师的必备条件: 前端开发有一定的设计能力,一般三年开发经验的同学,面试必须考设计能力 成为项目技术负责人,设计 ...

  4. vue2.* 目录结构分析 数据绑定 循环渲染数据 数据渲染02

    一.目录 结构分析 node_modules:项目依赖文件(也可以说是模块) src:开发时所用的资源 assets:静态资源文件 App.vue:根组件(最基础的公共页面) main.js:实例化v ...

  5. 【bootstrap】面包屑导航(Breadcrumbs)

    .breadcrumb > li + li:before { color: #CCCCCC; content: "/ "; padding: 0 5px; } <ol ...

  6. 5.3.1 RPC端点RpcEndpoint

    ThreadSafeRpcEndpoint对消息的处理都是串行的,即前一条消息处理完才能接着处理下一条消息.ThreadSafeRpcEndpoint的继承体系如图5-3所示. 5.3.2 RPC端点 ...

  7. notepad++怎样添加文件目录

    需要安装一个Explorer.dll文件 方法一:这个方法我个人试了不成功,可能因为版本问题,进入后选择Explorer进行安装 方法二:网上下载      Explorer.dll文件,放到\\No ...

  8. Ubuntu安装MySQL/MariaDB

    安装MariaDB/MySQL MariaDB是MySQL的分支,与MySQL高度兼容,几乎所有的命令都一样.MariaDB是由前MySQL的开发人员离开Sun公司后开发的,目的是为了防止Oracle ...

  9. vlc源码分析(三) 调用live555接收RTSP数据

    首先了解RTSP/RTP/RTCP相关概念,尤其是了解RTP协议:RTP与RTCP协议介绍(转载). vlc使用模块加载机制调用live555,调用live555的文件是live555.cpp. 一. ...

  10. 全面理解 ASP.NET Core 依赖注入 (转载)

    DI在.NET Core里面被提到了一个非常重要的位置, 这篇文章主要再给大家普及一下关于依赖注入的概念,身边有工作六七年的同事还个东西搞不清楚.另外再介绍一下.NET  Core的DI实现以及对实例 ...