题目描述
定义如下规则:
- 空串是「平衡括号序列」
- 若字符串 S S S 是「平衡括号序列」,那么 [ S ] \texttt{[}S\texttt] [S] 和 ( S ) \texttt{(}S\texttt) (S) 也都是「平衡括号序列」
- 若字符串 A A A 和 B B B 都是「平衡括号序列」,那么 A B AB AB(两字符串拼接起来)也是「平衡括号序列」。
例如,下面的字符串都是平衡括号序列:
()
,[]
,(())
,([])
,()[]
,()[()]
而以下几个则不是:
(
,[
,]
,)(
,())
,([()
现在,给定一个仅由 (
,)
,[
,]
构成的字符串
s
s
s,请你按照如下的方式给字符串中每个字符配对:
- 从左到右扫描整个字符串。
- 对于当前的字符,如果它是一个右括号,考察它与它左侧离它最近的未匹配的的左括号。如果该括号与之对应(即小括号匹配小括号,中括号匹配中括号),则将二者配对。如果左侧未匹配的左括号不存在或与之不对应,则其配对失败。
配对结束后,对于 s s s 中全部未配对的括号,请你在其旁边添加一个字符,使得该括号和新加的括号匹配。
输入格式
输入只有一行一个字符串,表示 s s s。
输出格式
输出一行一个字符串表示你的答案。
样例 #1
样例输入 #1
([()
样例输出 #1
()[]()
样例 #2
样例输入 #2
([)
样例输出 #2
()[]()
提示
数据规模与约定
对于全部的测试点,保证
s
s
s 的长度不超过 100,且只含 (
,)
,[
,]
四个字符。
解题思路:
首先解释题意:题意并不是很清晰,这里进一步解释一下
题目要求最终得到的括号序列仍然是平衡括号序列,并不是说只要有能匹配的括号即可
就是说如果括号序列为
([)]
那么得出的结果应该是
()[()]
两个小括号是不能匹配的
这样我们可以想到用栈来实现代码
首先说明匹配机制:
int main()
{
string str;
stack<char> char_stack;
cin >> str;
int len = str.size();
for (int i = 0; i < len; i++)
{
switch (str[i])
{
case '(':
char_stack.push(str[i]);
break;
case '[':
char_stack.push(str[i]);
break;
case ')':
{
if (char_stack.top() == '(')
{
char_stack.pop();
}
}
case ']':
if (char_stack.top() == '[')
{
char_stack.pop();
}
default:
break;
}
}
}
这里可以采用两种方式实现题中要求的输出效果
要解决的核心问题就是如何区分已经匹配的括号和未匹配的括号
方法一:引入另一个匹配字符串
int main()
{
string str, match_str = "";
stack<char> char_stack, index_stack;
cin >> str;
int len = str.size();
for (int i = 0; i < len; i++)
{
switch (str[i])
{
case '(':
{
char_stack.push(str[i]);
index_stack.push(i);//如果匹配成功匹配,通过该索引对应元素修改状态
match_str += ')';//默认状态是未匹配
break;
}
case '[':
{
char_stack.push(str[i]);
index_stack.push(i);//如果匹配成功匹配,通过该索引对应元素修改状态
match_str += ']';//默认状态是未匹配
break;
}
case ')':
{
if (!char_stack.empty() && char_stack.top() == '(')//注意:一定要先判断栈是否为空
{
char_stack.pop();
match_str[index_stack.top()] = '\0';//修改状态为已经匹配
index_stack.pop();
match_str += '\0';
}
else
{
match_str += '(';
}
break;
}
case ']':
{
if (!char_stack.empty() && char_stack.top() == '[')//注意:一定要先判断栈是否为空
{
char_stack.pop();
match_str[index_stack.top()] = '\0';//修改状态为已经匹配
index_stack.pop();
match_str += '\0';
}
else
{
match_str += '[';
}
break;
}
default:
break;
}
}
}
然后实现输出的代码如下
for (int i = 0; i < len; i++)
{
if (match_str[i] == '\0')//如果str[i]的状态为已匹配
{
cout << str[i];
}
else//如果str[i]的状态为未匹配
{
if (match_str[i] == '[' || match_str[i] == '(')
{
cout << match_str[i] << str[i];
}
else
{
cout << str[i] << match_str[i];
}
}
}
方法一实现完成
(ps:如果超时的话可能是由于字符串的拼接操作耗费时间,可以尝试字符数组)
方法二:通过值的修改来修改括号的状态,如未匹配的括号值为1,已匹配的括号值为2
方法二的完整代码如下
#include <iostream>
#include <stack>
using namespace std;
int main()
{
string str;
cin >> str;
stack<char> char_stack, index_stack;
int len = str.size();
for (int i = 0; i < len; i++)//共有六种状态:1-(),2-[],3-(,4-),5-[,6-]
{
switch (str[i])
{
case '(':
{
char_stack.push(str[i]);
index_stack.push(i);//如果匹配成功匹配,通过该索引对应元素修改状态
str[i] = 1;//默认状态是未匹配
break;
}
case '[':
{
char_stack.push(str[i]);
index_stack.push(i);//如果匹配成功匹配,通过该索引对应元素修改状态
str[i] = 2;//默认状态是未匹配
break;
}
case ')':
{
if (!char_stack.empty() && char_stack.top() == '(')//注意:一定要先判断栈是否为空
{
char_stack.pop();
str[index_stack.top()] = 3;//修改状态为已经匹配
index_stack.pop();
str[i] = 4;
}
else
{
str[i] = 1;
}
break;
}
case ']':
{
if (!char_stack.empty() && char_stack.top() == '[')//注意:一定要先判断栈是否为空
{
char_stack.pop();
str[index_stack.top()] = 5;//修改状态为已经匹配
index_stack.pop();
str[i] = 6;
}
else
{
str[i] = 2;
}
break;
}
default:
break;
}
}
for (int i = 0; i < len; i++)
{
switch (str[i])
{
case 1:
cout << "()";
break;
case 2:
cout << "[]";
break;
case 3:
cout << '(';
break;
case 4:
cout << ')';
break;
case 5:
cout << '[';
break;
case 6:
cout << ']';
break;
default:
break;
}
}
}