括号配对问题

本文讨论了如何利用栈来解决括号配对问题。根据括号匹配的规则,如偶数长度、左括号必须在前、不交叉嵌套,提出了从后向前匹配括号的策略。通过栈的后进先出特性,实现匹配过程,匹配成功则消除括号,否则判断整个序列不匹配。文章附有解题思路和代码实现。
摘要由CSDN通过智能技术生成

括号配对问题

时间限制: 3000 ms  |  内存限制: 65535 KB
难度: 3
描述
现在,有一行括号序列,请你检查这行括号是否配对。
输入
第一行输入一个数N(0<N<=100),表示有N组测试数据。后面的N行输入多组输入数据,每组输入数据都是一个字符串S(S的长度小于10000,且S不是空串),测试数据组数少于5组。数据保证S中只含有"[","]","(",")"四种字符
输出
每组输入数据的输出占一行,如果该字符串中所含的括号是配对的,则输出Yes,如果不配对则输出No
样例输入
3
[(])
(])
([[]()])
样例输出
No
No
Yes

小刀一试:

我们观察到如果括号匹配的话必然有如下规则:

1、匹配的括号序列长度必然为偶数

2、第一个括号必须为左括号('(' 或 '[' )

3、括号不会交叉嵌套出现(如:([)] 就不符合),具有对称性。

我们就根据上面的规则经行判断。

首先需要处理的问题是利用什么数据结构?选对数据结构能大大简化问题

如果我们当前看到了一个左括号,则我们不能判断其与哪个括号匹配,因为与之匹配的括号必定在其后面,因此我们还需要向后搜索。但是当我们看到一个右括号的时候,我们必然可以判断其与前面哪个括号匹配(或者找不到匹配)。因此我们的第一个匹配是从后面第一个右括号开始的,当我们找到一对匹配的括号的时候,我们就可以把这对括号消除,然后继续找下一个右括号,继续消除,直到算法结束。显然我们遇到的第一个右括号必定与其前一个括号匹配,否则不满足第三条规则。当我们删除了第一个匹配的括号之后,剩下的括号形成了一个新的序列。于是可以应用上面的思路继续经行匹配。

从以上分析可以观察到,我们遇到左括号的时候是继续向后搜索,当遇到第一个右括号的时候,与其前一个符号进行括号匹配判断,匹配则删除这对括号,否则可以判断整个序列的括号是不匹配的。对于左括号的删除操作有如下特性:后面的括号先被删除,最前面的括号最后被删除。这个规则符合栈的后进先出的规则。所以暂时以栈为数据结构尝试进行解题,看看是否能行。下面根据以上思路贴出代码:

#include <iostream>
#include <string>
#include <stack>

#define IS_LEFT(c)	c == '(' || c == '['
#define IS_RIGHT(c) c == ')' || c == ']'
#define IS_MATCH(l,r) (l=='(' && r==')')||( l=='['&& r==']' )

using namespace std;
int main()
{
	int times;
	cin >> times;
	string str;
	while( times-- )
	{
		cin >> str;
		stack<char> s;
		if( IS_RIGHT( str[0] ) || (str.size()%2 != 0 ) )
		{
			cout << "No" << endl;
			continue;
		}
		
		s.push( str[0] );
		int i = 1;
		for( ; i < str.size(); i++ )
		{
			if( IS_LEFT(str[i]) )
			{
				s.push( str[i] );
			}
			else
			{
				if( s.empty() )
				{
					cout << "No" << endl;
					break;
				}

				if( IS_MATCH( s.top(), str[i] ) )
					s.pop();
			}
		}
		if( i < str.size() )
			continue;
		if( s.empty() )
			cout << "Yes" << endl;
		else
			cout << "No" << endl;
	}
	//system( "pause" );
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值