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; }