贪心,left_min[i]记录在保证1~i合法的情况下1~i最少的‘(’个数,left_max[i]记录在保证1~i合法的情况下1~i最多的‘(’个数,right_min[i]记录在保证(i+1)~n合法的情况下(i+1)~n最少的‘(’个数,right_max[i]记录在保证(i+1)~n合法的情况下(i+1)~n最多的‘(’个数。因为左括号是向右匹配的,所以向右贪心,而右括号是向左匹配的,所以向左贪心。
在贪心的过程中,检查是否会出现非法情况,min[i]>max[i]。出现则无解,否则有解。
多解的情况判断需要判断区间[left_min[i],left_max[i]]与[right_min[i],right_max[i]]的区间交是否长度大于1。只要存在一处区间交长度大于1,那么说明在这一处可以有多种情况,即存在多解。
#include<bits/stdc++.h>
#define rep(a,b,c) for(int a=b;a<c;a++)
#define LL long long
using namespace std;
const int maxn=1e6+5;
const int Inf=1e9+7;
const int mod=3;
char s[maxn];
int n;
int left_min[maxn], left_max[maxn];
int right_min[maxn], right_max[maxn];
int main()
{ int T;
while(~scanf("%s",s+1)){
n=strlen(s+1);
if(n%2) {puts("None");continue;}
int no_ans=0;
left_min[0]=left_max[0]=0;
for(int i=1;i<=n;i++){
if(s[i]=='('){
left_min[i]=left_min[i-1]+1;
left_max[i]=left_max[i-1]+1;
}else if(s[i]==')'){
if(!left_min[i-1]) left_min[i]=1;//from left,we can let left brackets more than rights
else left_min[i]=left_min[i-1]-1;
left_max[i]=left_max[i-1]-1;
}else{
if(!left_min[i-1]) left_min[i]=1;
else left_min[i]=left_min[i-1]-1;
left_max[i]=left_max[i-1]+1;
}
if(left_min[i]>left_max[i]) no_ans=1;
}
if(no_ans){puts("None");continue;}
right_min[n]=right_max[n]=0;
for(int i=n;i>0;i--){
if(s[i]=='('){
if(!right_min[i]) right_min[i-1]=1;
else right_min[i-1]=right_min[i]-1;
right_max[i-1]=right_max[i]-1;
}else if(s[i]==')'){
right_min[i-1]=right_min[i]+1;
right_max[i-1]=right_max[i]+1;
}else{
if(!right_min[i]) right_min[i-1]=1;
else right_min[i-1]=right_min[i]-1;
right_max[i-1]=right_max[i]+1;
}
if(right_min[i]>right_max[i]) no_ans=1;
}
if(no_ans) {puts("None");continue;}
int multi_ans=0;
for(int i=1;i<=n;i++){
int l=max(left_min[i], right_min[i]);
int r=min(left_max[i], right_max[i]);
if(l<r) multi_ans=1;
}
if(multi_ans) puts("Many");
else puts("Unique");
}
return 0;
}