6799 Parentheses Matching

传送门

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)
Total Submission(s): 589    Accepted Submission(s): 253

Problem Description
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 S=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 k such that:

    ● 1≤k≤n, and
    ● the first (k−1) characters of A and that of B are exactly the same, and
    ● the k-th character of A is 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≤105), 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≤105), 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×106.
 
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!
()
()()
 
(())()(())

题解:

题意:给你一个字符串,里面有'('、 ')'、 '*'三种字符,*可以转化为左括号、右括号、空字符,现在让你利用*给字符串里面的左右括号进行匹配,如果无法匹配,输出No solution! ,否则输出字典序最小的匹配好的字符串。

思路:为了字典序最小,考虑左括号应该尽量往左边放,右括号应该尽量往右边放。于是我们分两种情况讨论,1、从左往右枚举,发现右括号多于左括号,就在左侧补上左括号,2、从右往左枚举,发现左括号多于右括号,就在右侧补上右括号。

#include <iostream>
#include <algorithm>

using namespace std;

int main()
{
	int t;
	cin>>t;
	while(t--)
	{ 
		string s;
		cin>>s;
		int num=0,cnt=0;//num用于判断左右括号数量是否相等,cnt用于寻找*,每次寻找从上一次寻找到的*位置的下一个位置开始,
		//因此第二层循环总共是s.length()次 
		bool flag=1;//用于判断是否无解,0表示无解 
		for(int i=0;i<s.length();i++)//从左到右枚举,在左边补充左括号
		{
			if(s[i]=='(') num++;
			else if(s[i]==')') num--;
			if(num<0)//右括号数量比左括号大1,在当前位置之前寻找*转化为左括号以实现平衡
			{
				for(int j=cnt;j<i;j++)
				{
					if(s[j]=='*') 
					{
						s[j]='(';
						cnt=j+1;
						num++;
						break; 
					}
				}
			} 
			if(num<0)//没有寻找到*转化为左括号,无解 
			{
				flag=0;
				break;
			} 
		}
		num=0,cnt=s.length()-1;
		for(int i=s.length()-1;i>=0;i--)
		{
			if(s[i]==')') num++;
			else if(s[i]=='(') num--;
			if(num<0)
			{
				for(int j=cnt;j>i;j--)
				{
					if(s[j]=='*')
					{
						s[j]=')';
						cnt=j-1;
						num++;
						break;
					}
				}
			}
			if(num<0) 
			{
				flag=0;
				break;
			}
		}
		if(!flag) cout<<"No solution!"<<endl;
		else 
		{
			for(int i=0;i<s.length();i++)
			{
				if(s[i]!='*') printf("%c",s[i]);	
			}	
			cout<<endl;
		} 
	} 
	
	return 0;	
} 

附:发现有时候算法题看起来很难,可真正实现了,思想确实很简单,究其原因,应该是自己想复杂了。很多算法题就像递归一样,应该把复杂的问题,转化为小问题,抓住问题的本质,只要抓住了本质,就不用考虑那么多其他复杂的东西了,实现起来也简单了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值