2014.8.5 - 多校5

本文详细解析了HDU-4915括号序列问题的算法思路,介绍了如何通过正向和反向扫描字符串来确定括号配对的可能性,并通过实例演示了如何判断括号序列的有效性和唯一性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://blog.sina.com.cn/s/blog_6bddecdc0102uz53.html

hdu-4915-Parenthese sequence

problem

给你一个字符串,长度是[1, 1e6], 只有?()三种字符。

1.空串可以。

2.如果a串可以,那么(a)可以。

3.如果a串和b串可以,那么ab串可以。

?可以当(或),问你可以的串没有,还是唯一,还是不唯一。

think

如果长度是奇数不可以。

两头一定是(和)。

从后往前每个点记录,包括这个点往后最少最多有几个右括号还没匹配。设这两个数组分别是mi和mx

中间过程如果有最多的出现了负数,就是不可以的。

如果到第一个字符最少有0个右括号没匹配,就是可以的。

从前往后每个点记录,包括这个点往前最少最多有几个左括号还没匹配。设这两个数组分别是mi1和mx2

如果碰到?判断是不是即可以是(也可以是)。如果有一个?可以,那么就是Many,?都只能当(或),就是Unique。

判断?能不能是(:mi1[i-1] < mx[i+1],即mi1[i-1] + 1 <= mx[i+1] ,表示?是左括号,依然是满足的,因为如果是mi1[i-1] + 1 > mx[i+1] 表示不可以。

判断?能不能是):mi[i+1] < mx1[i-1]

code

const int N = 1111111;
int mi[N];
int mx[N];
int mi1[N];
int mx1[N];
char str[N];

int main(){
    int T, tt = 0;
    while(scanf("%s", str) != EOF){
        int n = strlen(str);
        if(n & 1){
            puts("None");
            continue;
        }
        if(str[0] == ')' || str[n-1] == '('){
            puts("None");
            continue;
        }
        str[0] = '(';
        str[n-1] = ')';
        mi[n-1] = 1;
        mx[n-1] = 1;
        bool ok = true;
        for(int i = n-2; i >= 0; --i){
            if(str[i] == '?'){
                mi[i] = max(0, mi[i+1] - 1);
                mx[i] = mx[i+1] + 1;
            } else if(str[i] == ')'){
                mi[i] = mi[i+1] + 1;
                mx[i] = mx[i+1] + 1;
            } else {
                mi[i] = max(0, mi[i+1] - 1);
                mx[i] = mx[i+1] - 1;
                if(mx[i] < 0) ok = false;
            }
        }
        if(mi[0] != 0) ok = false;
        if(ok == false){
            puts("None");
            continue;
        }
        mi1[0] = 1;
        mx1[0] = 1;
        bool many = false;
        for(int i = 1; i < n; ++i){
            if(str[i] == '?'){
                if(mi1[i-1] < mx[i+1] && mi[i+1] < mx1[i-1]) many = true;
                mi1[i] = max(0, mi1[i-1] - 1);
                mx1[i] = mx1[i-1] + 1;
            } else if(str[i] == '('){
                mi1[i] = mi1[i-1] + 1;
                mx1[i] = mx1[i-1] + 1;
            } else {
                mi1[i] = max(0, mi1[i-1] - 1);
                mx1[i] = mx1[i-1] - 1;
                if(mx1[i] < 0) ok = false;
            }
        }
        if(many) puts("Many");
        else puts("Unique");
    }
    return 0;
}
/*
??
????
(??
??))
(????)
()??
((??))
()??()
((((???)(??)))
((((???)()))))
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值