hdu 4915 括号匹配+巧模拟

http://acm.hdu.edu.cn/showproblem.php?pid=4915

给定一个序列,由()?组成,其中?可以表示(或者),问说有一种、多种或者不存在匹配。

从左向右,优先填满n/2个左括号,继续填充右括号。如果过程中出现矛盾(右括号数超过左括号数),则为None,否则要判断唯一解还是多解。

之前遍历的时候记录恰好填满了n/2个左括号后,第一次添加右括号的位置强行设置成左括号,问号数自减一,在跑一遍,若能跑通则说明有多解,否则单一解

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#define RD(x) scanf("%d",&x)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define clr0(x) memset(x,0,sizeof(x))

typedef long long LL;

int n;
char s[1000010];
int a[1000005],b[1000005],tot,t,m;
int main()
{
    while (scanf("%s",s)!=EOF){
        n=strlen(s);
        int i,j,k;
        tot = m = t = 0;
        if(n%2){puts("None");continue;}
        for(int i = 0;i < n;++i){
            if(s[i] == '('){
                a[i] = b[i] = 1;
                tot++;
            }else if(s[i] == ')')
                a[i] = b[i] = -1;
            else{
                a[i] = b[i] = 0;
                m++;
            }
        }
        t = n-tot-m;
        if(tot > n/2 || t > n/2){puts("None");continue;}
        t = n/2 - tot;
        int pos = -1;
        for (k = 0,i = 0;i < n;++i){
            if (a[i] == 0){
                if (t)
                    --t,k++;
                else{
                    if(pos == -1)
                        pos = i;
                    k--;
                }
            }
            else k+=a[i];
            if (k < 0){
                puts("None");
                goto end;
            }
        }
        if(k != 0){
            puts("None");
            continue;
        }
        t = n/2 - tot;
        if(t == m || t == 0){
            puts("Unique");
            continue;
        }
        --t;
        for(b[pos] = 1,k = 0,i = 0;i<n;++i){
            if(b[i] == 0){
                if (t) --t,k++;
                else k--;
            }
            else k += b[i];
            if (k < 0){
                puts("Unique");
                goto end;
            }
        }
        puts("Many");
        end:;
    }
    return 0;
}
时间: 2024-10-13 16:56:12

hdu 4915 括号匹配+巧模拟的相关文章

hdu 4915 Parenthese sequence(模拟)2014多校训练第5场

Parenthese sequence                                                                     Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description bobo found an ancient string. The string contains only t

hdu 4915 Parenthese sequence (贪心+模拟)

题目大意: 一个序列中有左括号和右括号,还有问号,问号可以任意转换成左右括号. 问这个序列有多少种情况的转变使得这个序列变成合法的括号匹配序列. 思路分析: 首先我们分析一下,如何使得一个序列是合法的括号匹配序列. 我们很容易想到的是用栈模拟匹配过程. 当遇到左括号就进栈,当遇到右括号就让栈顶的左括号出栈. 那么在模拟的过程中,造成这个序列的不合法的原因只有当右括号来的时候,此时的栈已经为空. 这里补充一句,一旦一个序列给定,那么这里面的问号有多少变成左括号,多少变成右括号,是一定的. 看完以上

HDU 4915 Parenthese Sequence 思维+模拟

题意:给出括号序列s,其中有'?'表示可以为'('或')'.|s|<=1e6,问将这些'?'代替后,s是否合法,若合法 是否有多解? 首先:把已经匹配的丢出去,不影响序列的合法性则 维护前缀i '('最多和最少未匹配的个数,对后缀i维护')'最多和最少未匹配的个数  (还剩个数)当max[i]<0 说明某个'('或')'不够匹配为无解.假如后缀i最少有x个')',则前缀i-1最少要有x个'(' 后缀i最多有y个')' 前缀i-1'('个数不多于y则前面左括号的范围就为[x,y]若y-x+1&g

模拟 --- 简单括号匹配

Parencodings Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19067   Accepted: 11502 Description Let S = s1 s2...s2n be a well-formed string of parentheses. S can be encoded in two different ways: q By an integer sequence P = p1 p2...pn

HDU 3351 Seinfeld(括号匹配)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3351 解题报告:输入一个只有'{'跟'}'的字符串,有两种操作,一种是把'{'变成'}',另一种是'}'变成'{',问你要把这个字符串的括号变成合法的最少需要多少次操作. 在刷DP专题,居然有个这个题目,看起来也像是DP,一直在想用DP怎么做,始终没做出来,最后试下直接字符串匹配居然A了.跟普通的字符串匹配的区别就是 在插入'}'这个的时候判断一下栈是不是为空,如果栈为空,则把这个'}'改为'{'再

STL版 括号匹配(感觉不如之前自己用数组模拟的跑的快)

数据结构实验之栈四:括号匹配 Time Limit: 1000MS Memory limit: 65536K 题目描述 给你一串字符,不超过50个字符,可能包括括号.数字.字母.标点符号.空格,你的任务是检查这一串字符中的( ) ,[ ],{ }是否匹配. 输入 输入数据有多组,处理到文件结束. 输出 如果匹配就输出“yes”,不匹配输出“no” 示例输入 sin(20+10) {[}] 示例输出 yes no 注意:读入的字符串里可能含有空格哦! #include <iostream> #i

HDU 4915 Parenthese sequence

HDU 4915 Parenthese sequence 题目链接 题意:给定一个有?的左右括号串,?能替代为'('或')',问括号匹配是否唯一或多种或不可能 思路:先从右往左扫一边,维护一个up, down表示当前位置右边右括号剩余个数的上限和下限,如果维护完后起始位置的下限为0,那么就是可以的,因为为0就代表没有多余的右括号.然后在从左往右扫一遍,和上面一样的处理,只是遇到每个问号的位置时,试一下左括号和右括号,如果都满足,表示这个位置能放左右括号,是多种可能,如果所有?都只有唯一的方法,那

hdu 4915 Parenthese sequence(高效)

题目链接:hdu 4915 Parenthese sequence 题目大意:给定一个序列,由(,),?组成?可以表示(或者),问说有一种.多种或者不存在匹配. 解题思路:从左向右,从右向左,分别维护左括号和右括号可能的情况,区间上下界.如果过程中出现矛盾,则为None,否则要判断唯一解还是多解.枚举每个问号的位置,假设该问号可为左右括号,则有多解. #include <cstdio> #include <cstring> #include <algorithm> us

HDU 4915 多校5 Parenthese sequence

比赛的时候想了一个自认为对的方法,WA到死,然后还一直敲下去,一直到晚上才想到反例 找是否存在解比较好找,这种左右括号序列,把(当成1,把)当成-1,然后从前往后扫,+1或者-1 遇到?就当初(,然后如果扫到最后 中间没有出现负数说明左括号没问题 然后同样的方法从后往前扫,判断右括号那里是不是有问题即可.都没问题就有解,否则无解 当然应该要先判断下序列长度是不是偶数,奇数肯定是无解 至于为什么要像之前的处理即可判断有无解,首先只有正好走完的时候 和值为0才是真正合法(因为这个时候左右括号都对应了