题意:
给一个只有’(’ 、’)’、’*'组成的字符串,让进行括号匹配,其中 星号可以是空字符、左括号或者右括号都行。让你构造最短的满足题意的字符串,要求字典序最短.
思路:
直接去用栈匹配即可。开一个栈存左括号,开一个双端队列存星号的位置。
1、如果是左括号,直接入栈。如果是星号,直接丢进队列中。
2、如果是右括号,优先看栈中是不是存在左括号,存在的话,将栈顶的左括号弹出。
3、如果栈中不存在,那么就看队列中是不是存在星号,我们优先取位置靠前的星号,这样能保证字典序最小,把最前面的星号的位置改成左括号,弹出这个星号。
如果都不存在,说明前缀的右括号数量大于前缀的左括号的数量加星号的数量,显然不存在解决方案。
一次匹配操作结束后,我们去看栈是不是为空,如果不为空,也就是栈内还有左括号,我们取队列中的星号去匹配,这里我们取的星号的位置要从最后面的取,这样保证字典序最小,注意星号的位置一定要大于左括号的位置,不然是无法配对的。如果左括号无法全部配对,那么就没有解决方案
总的来说就是,首先直接去匹配,是看右括号能不能匹配完,然后再去匹配栈内剩余的左括号,也就是看左括号能不能匹配完。
#include<bits/stdc++.h>
using namespace std;
int main(){
int T;cin>>T;
while(T--){
stack<int> a;
deque<int> q;
string s;cin>>s;
int flag=0;
for(int i=0;s[i];i++){
if(s[i]=='*') q.push_back(i);
else if(s[i]==')') {
if(!a.empty()) a.pop();
else if(!q.empty()){
s[q.front()]='(';
q.pop_front();
}
else flag=1;
}
else a.push(i);
}
while(!a.empty()){
if(!q.empty() && q.back()>a.top()){
s[q.back()]=')';
q.pop_back();
a.pop();
}
else {
flag=1;
break;
}
}
if(flag) cout<<"No solution!";
else for(auto i:s) if(i!='*') cout<<i;
cout<<endl;
}
return 0;
}