题目传送门 点这里
括号匹配,有的位置不确定,要求这个串的子列都是非法的匹配,只有原串才是合法的。现在求是否有这样一个字符串,如果有,输出。
根据题意,易知当这个序列的合法时,左右括号的个数应当是相等且等于字符串长度len的一半。所以我们可以先去统计左右括号给出的个数,如果其中一个超出了len/2,那么一定不存在合法序列。如果 ( 不足,那么就优先从序列的最左边的位置补足 ( ,因为从最左边补是最优的。之后再补足 ) 。
最后验证这个序列是否满足要求,是否是所有从最左端起的子列都非法,原串合法
#include <stdio.h>
#include <climits>
#include <cstring>
#include <time.h>
#include <math.h>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <utility>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define ll long long
#define Pair pair<int,int>
#define re return
#define getLen(name,index) name[index].size()
#define mem(a,b) memset(a,b,sizeof(a))
#define Make(a,b) make_pair(a,b)
#define Push(num) push_back(num)
#define rep(index,star,finish) for(register int index=star;index<finish;index++)
#define drep(index,finish,star) for(register int index=finish;index>=star;index--)
using namespace std;
int len;
string store;
bool matched[300005];
int main(){
ios::sync_with_stdio(false);
cin>>len;
cin>>store;
if(len%2){
cout<<":(\n";
re 0;
}
int n1=0,n2=0;
int temp=0;
for(char c : store){
if(c=='(')
n1++;
if(c==')')
n2++;
}
if(n1>len/2 || n2>len/2){
cout<<":(\n";
re 0;
}
int num=len/2-n1;
for(char &c : store){
if(c=='?'){
if(num){
c='(';
num--;
}else
c=')';
}
}
bool safe=true;
int pos=0,stc=0;;
while(pos<len-1){
if(store[pos]=='(')
stc++;
else{
stc--;
if(stc<=0){
safe=false;
break;
}
}
pos++;
}
if(safe && stc==1){
cout<<store<<endl;
}else{
cout<<":(\n";
}
re 0;
}