题解:括号匹配
题目
题目描述
给定一字符串,只由 (、) 和 * 三种字符组成,你需要替换掉所有的 * 使得整个字符串变为一个 平衡的括号串。你可以选择将一个 * 替换为一个 ( 或 ),也可以直接删掉这个 *(也就是替换为一个 空串)。
一个平衡的括号串定义如下:
- 空串是平衡的括号串。
- 如果 \(A,B\) 均为平衡的括号串,那么 \(AB\) 也是一个平衡的括号串(这里 \(AB\) 指将 \(A\) 与 \(B\) 拼接起来)。
- 如果 \(A\) 是一个平衡的括号串,那么 \((A)\) 也是一个平衡的括号串。
给定这样一个含有 * 的括号串,输出替换掉所有 * 后得到的一个平衡的括号串。由于可能存在多种答案,所以本题只要求选手输出长度最短且字典序最小的括号串。如果不能得到一个平衡的括号串,输出 No solution!。
输入格式
输入仅一行,即一个字符串,只含有 (、) 以及 * 三种字符。
输出格式
输出一行,即替换掉所有 * 后长度最短且字典序最小的平衡括号串。如果无解,输出 No solution!。
输入输出样例
输入 #1
((***)()((**
输出 #1
(())()(())
说明/提示
设字符串长度为 \(n\)。
对于 \(20\%\) 的数据,有 \(1\leq n\leq15\)。
对于 \(40\%\) 的数据,有 \(1\leq n\leq10^3\)。
对于 \(100\%\) 的数据,有 \(1\leq n\leq10^5\)。
题解
贪心
诸如此类的“括号匹配”问题,先考虑一个栈 \(s\) 存储 (,用来和 ) 匹配。
因为只有一种括号 ( 和 ),因此无需考虑“括号嵌套”的问题。即对于括号 \(\color{red}()\color{blue}()\),变成 \(\color{red}(\color{blue}()\color{red})\) 和 \(\color{red}(\color{blue}(\color{red})\color{blue})\) 都是合法的。
因此考虑一种贪心:
-
长度最小,因此让
*尽可能地被替换为空串,即让字符串中原有的(和)尽可能互相匹配。 -
使用双端队列 \(t\) 维护
*的下标,栈 \(s\) 维护未匹配的(的下标。先扫一遍字符串,将所有
*的下标加入 \(t\)。则在扫字符串的时候,
-
遇到
(就将其下标加入栈 \(s\)。 -
遇到
*直接跳过。 -
遇到
)时,-
如果 \(s\) 中还有未匹配的
(,直接匹配最好,即将 \(s\) 的栈顶出栈。 -
否则,需要动用
*来保证字符串的合法性。使用最左边的即可,因为使用更靠右的*有可能在)的右边。也就是说,如果 \(t\) 的队首在
)的右边,则无解。
-
-
扫完之后,\(s\) 中可能还有没匹配的
(,同理使用 \(t\) 的队尾匹配即可。
-
AC 代码
//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
string a;
vector<int>s;
deque<int>t;
int main(){
/*freopen("test.in","r",stdin);
freopen("test.out","w",stdout);*/
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>a;
for(int i=0;i<a.size();i++){
if(a[i]=='*'){
t.push_back(i);
}
}
for(int i=0;i<a.size();i++){
if(a[i]=='('){
s.push_back(i);
}else if(a[i]==')'){
if(s.size()){
s.pop_back();
}else{
if(t.size()&&t.front()<i){
a[t.front()]='(';
t.pop_front();
}else{
cout<<"No solution!\n";
return 0;
}
}
}
}
while(s.size()){
if(s.back()>=t.back()){
cout<<"No solution!\n";
return 0;
}
a[t.back()]=')';
t.pop_back();s.pop_back();
}
for(char i:a){
if(i!='*'){
cout<<i;
}
}
cout.flush();
/*fclose(stdin);
fclose(stdout);*/
return 0;
}

浙公网安备 33010602011771号