HDU6799 Parentheses Matching(贪心/括号匹配)
Posted lipoicyclic
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU6799 Parentheses Matching(贪心/括号匹配)相关的知识,希望对你有一定的参考价值。
Given a string P
consisting of only parentheses and asterisk characters (i.e. "(", ")" and ""), you are asked to replace all the asterisk characters in order to get a balanced parenthesis string with the shortest possible length, where you can replace each "" by one "(", or one ")", or an empty string "".
A parenthesis string S is a string consisting of only parentheses (i.e. "(" and ")"), and is considered balanced if and only if:
● S is an empty string, or there exist two balanced parenthesis strings A
and B such that SS=AB, or there exists a balanced parenthesis string C such that S=(C*)
.
For instance, "", "()", "(())", "()()", "()(())" are balanced parenthesis strings.
Due to some notorious technical inability, if there are several solutions with the shortest possible length, then you have to report the smallest possible one in lexicographical order.
For every two different strings A
and B
of the same length n
, we say A is smaller than B in lexicographical order if and only if there exists some integer kk
such that:
● 1≤k≤n1≤k≤n, and the first (k?1) characters of Aand that of B are exactly the same, and the k-th character of Ais smaller than that of B
.
For instance, "()(())" is smaller than "()()()", and in this case, k=4
.
Input
There are several test cases.
The first line contains an integer T
(1≤T≤(10^5)), denoting the number of test cases. Then follow all the test cases.
For each test case, the only line contains a string of length n
(1≤n≤(10^5)), denoting the string P that consists of only parentheses and asterisk characters.
It is guaranteed that the sum of n
in all test cases is no larger than (5 imes10^6)
.
Output
For each test case, output in one line "No solution!" (without quotes) if no solution exists, or otherwise the smallest possible solution in lexicographical order. Note that the output characters are case-sensitive.
Sample Input
5
*))*)
*(*)*
*)*(*
******
((***)()((**
Sample Output
No solution!
()
()()
(())()(())
啊我好菜我好菜我好菜
比赛时队友想出来的思路是首先对原串去括号,最终得到的朴素形式是 **)**)***)*****((*(( ***这样,即左半部分是星号和右括号,右半部分是左括号和星号,否则的话还能继续消括号。然后对于左半部分,尽可能靠左填充左括号(满足字典序最小);右半部分尽可能靠右填充右括号(满足字典序最小)。注意对于))*这样的得判断一下左半部分当前*的数目是否小于当前左括号的数目(可以用前缀和判断),右半部分同理。
证明引用一下题解:
注意到,如果有最短长度的合法解,则不会存在一个被替换为 “(” 的 “*” 在一个被替换为 “)” 的 “*” 右侧。假设存在这样的情况,则交换它们不会使解不合法,但交换后可以发现它们都可以替换为 “”, 这意味着存在更短长度的解,从而导出矛盾。 假设已经得到一个最短长度的合法解,则对于每个被替换为 “)” 的 “*”,如果其右侧存在被替换为 “” 的 “*”,则我们可以交换这两个字符的位置,新解的字典序不会更大,对于 “(” 同理。 因此最短长度的字典序最小合法解一定是替换最左侧的一部分 “*” 为 “(”,最右侧的一部分 “*” 为 “(”,而且它们的数量 cl,cr 满足 cl ?cr 是定值,于是我们可以二分查找最小的 cl 使得构造出的串为合 法解。
实际上,我们可以注意到 cl 和 cr 的值是可以直接根据已有括号算出的,因为我们加括号就是为了 抵消对应的括号带来的限制。
垃圾代码仅供提醒我是辣鸡
#include <bits/stdc++.h>
using namespace std;
bool vis[5000005];
char ss[5000005];
int sum_l[5000005], sum_r[5000005];
stack<int> s;//一开始写成stack<char>了 我裂开
stack<char> star;
int main()
{
//freopen("1009.in","r",stdin);
//freopen("my.out","w",stdout);
int t;
cin >> t;
while(t--)
{
scanf("%s",ss);
int len = strlen(ss);
int cnt_l = 0, cnt_r = 0;
while(s.size()) s.pop();
for(int i = 0; i < len; i++)
{
if(ss[i] == ‘(‘)
{
s.push(i);
vis[i] = 0;
}
else if(ss[i] == ‘*‘)
{
vis[i] = 0;
continue;
}
else if(ss[i] == ‘)‘)
{
if(s.size())
{
int left = s.top();
s.pop();
vis[left] = vis[i] = 1;
}
else
{
vis[i] = 0;
continue;
}
}
}
for(int i = 0; i < len; i++)
{
if(!vis[i] && ss[i] == ‘(‘) cnt_l++;
if(!vis[i] && ss[i] == ‘)‘) cnt_r++;
}
int i;
int ready1 = 0, ready2 = 0;
sum_r[len] = sum_l[len] = 0;
for(int i = 0; i < len; i++)
{
if(i == 0)
{
if(!vis[i] && ss[i] == ‘(‘) sum_l[0] = 1;
else sum_l[0] = 0;
continue;
}
sum_l[i] = sum_l[i - 1];
if(!vis[i] && ss[i] == ‘(‘) sum_l[i]++;
}
for(int i = len - 1; i >= 0; i--)
{
sum_r[i] = sum_r[i + 1];
if(!vis[i] && ss[i] == ‘)‘) sum_r[i]++;
}
bool flag = 1;
while(star.size()) star.pop();
for(i = 0; i < len; i++)
{
if(vis[i]) continue;
if(ss[i] == ‘(‘)
{
break;
}
if(ss[i] == ‘)‘)
{
if(star.size() < cnt_r - sum_r[i + 1])
{
flag = 0;
break;
}
}
if(ss[i] == ‘*‘) star.push(‘*‘);
if(ss[i] == ‘*‘ && ready1 < cnt_r)
{
ss[i] = ‘(‘;
ready1++;
}
}
while(star.size()) star.pop();
// for(i = len - 1; i >= 0; i--)
// {
// if(ss[i]==‘*‘&&!vis[i])cout<<"lol";
// }
for(i = len - 1; i >= 0; i--)
{
if(vis[i]) continue;
if(ss[i] == ‘)‘)
{
break;
}
if(ss[i] == ‘(‘)
{
if(star.size() < cnt_l - sum_l[i - 1])
{
flag = 0;
break;
}
}
if(ss[i] == ‘*‘) star.push(‘*‘);
if(ss[i] == ‘*‘ && ready2 < cnt_l)
{
ss[i] = ‘)‘;
ready2++;
}
}
//cout<<"ready :"<<ready1<<‘ ‘<<ready2<<endl;
//cout<<"cnt:"<<cnt_l<<‘ ‘<<cnt_r<<endl;
if(ready1 != cnt_r || ready2 != cnt_l || !flag)
{
cout << "No solution!" << endl;
}
else
{
for(i = 0; i < len; i++)
{
if(ss[i] == ‘*‘) continue;;
cout << ss[i];
}
cout << endl;
}
}
return 0;
}
//)**)(()*
以上是关于HDU6799 Parentheses Matching(贪心/括号匹配)的主要内容,如果未能解决你的问题,请参考以下文章
HDU 多校 6400 Parentheses Matrix(构造)
mt6799芯片资料mt6799芯片数据表mt6799芯片原理图