题目概述:
给定一个RBS(一定是合法的),它的括号表达式是否是唯一的。
贪心法一:
括号匹配问题:从左到右遍历,( 的数目应当不小于 ) 的数目,最后两者相等。
我们从左到右遍历,用 dep 表示 ( 的个数,没遇到一个 ( , dep 要加 1。我们用 now 表示 ? 的个数。
当我们遇到一个 ) 时,dep 要减 1, 如果dep 要小于 0 了,说明我们需要 之前的 ? 来当做 ( 用,因为这是个合法的 RBS, 所以我们的 ‘?’ 肯定是够用的,所以 now --, dep++, 这样一来 dep 一直都不会是一个负数。此外,当dep 为 0 且 ?的数目 为 1时,这个?必须转化为左括号。遍历结束后,还有 dep 个左括号,以及 now 个没有用过的 ? 号,如果两者相等,则所有的 ? 应该都是右括号,结果唯一。
下面看这个示例:? (?) ()? )
首先 now = 1, dep = 0, 这个必须为左括号,所以 now = 0, dep = 1;
遇到左括号, now = 0, dep = 2;
遇到?, now = 1, dep = 2;
遇到右括号, now = 1, dep = 1;
now = 1, dep = 2;
now = 1, dep = 1;
now = 2, dep = 1;
now = 2, dep = 0;
最后 now 不等于 dep, 则表示不可以。
贪心法二:
首先尽可能左边的? 填 左括号, 最后的一些 ? 填右括号。这是肯定能够成功地一组填法。
然后,我们交换 所填的最右边的 ( 和 所填入的最左边的 ) , 这样是我们构造出的最可能成功的另一种匹配方案,如果这种方案也可以成功地话,那么解法一定大于等于 2,否则只有 1.
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include <numeric>
#include <string>
int main() {
int T, now, dep, i, len;
cin >> T;
while (T--)
{
string s;
cin >> s;
len = s.size();
now = 0;
dep = 0;
for (i = 0; i < len; i++)
{
if (s[i] == '(')
dep++;
else if (s[i] == ')')
{
dep--;
if (dep < 0)
{
dep++;
now--;
}
}
else
now++;
if (dep == 0 && now == 1)
{
dep++;
now--;
}
}
if (dep == now)
cout << "YES\n";
else
cout << "NO\n";
}
}