codeforces1153C. Serval and Parenthesis Sequence

题目传送门 点这里

括号匹配,有的位置不确定,要求这个串的子列都是非法的匹配,只有原串才是合法的。现在求是否有这样一个字符串,如果有,输出。


根据题意,易知当这个序列的合法时,左右括号的个数应当是相等且等于字符串长度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;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值