括号配对问题
时间限制:
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" );
}