题解:括号匹配

数据包 洛谷自建题目

题目

题目描述

给定一字符串,只由 ()* 三种字符组成,你需要替换掉所有的 * 使得整个字符串变为一个 平衡的括号串。你可以选择将一个 * 替换为一个 (),也可以直接删掉这个 *(也就是替换为一个 空串)。

一个平衡的括号串定义如下:

  1. 空串是平衡的括号串。
  2. 如果 \(A,B\) 均为平衡的括号串,那么 \(AB\) 也是一个平衡的括号串(这里 \(AB\) 指将 \(A\)\(B\) 拼接起来)。
  3. 如果 \(A\) 是一个平衡的括号串,那么 \((A)\) 也是一个平衡的括号串。

给定这样一个含有 * 的括号串,输出替换掉所有 * 后得到的一个平衡的括号串。由于可能存在多种答案,所以本题只要求选手输出长度最短且字典序最小的括号串。如果不能得到一个平衡的括号串,输出 No solution!

输入格式

输入仅一行,即一个字符串,只含有 () 以及 * 三种字符。

输出格式

输出一行,即替换掉所有 * 后长度最短且字典序最小的平衡括号串。如果无解,输出 No solution!

输入输出样例

输入 #1

((***)()((**

输出 #1

(())()(())

说明/提示

设字符串长度为 \(n\)

对于 \(20\%\) 的数据,有 \(1\leq n\leq15\)

对于 \(40\%\) 的数据,有 \(1\leq n\leq10^3\)

对于 \(100\%\) 的数据,有 \(1\leq n\leq10^5\)

bracketSample.zip

题解

贪心

诸如此类的“括号匹配”问题,先考虑一个栈 \(s\) 存储 (,用来和 ) 匹配。

因为只有一种括号 (),因此无需考虑“括号嵌套”的问题。即对于括号 \(\color{red}()\color{blue}()\),变成 \(\color{red}(\color{blue}()\color{red})\)\(\color{red}(\color{blue}(\color{red})\color{blue})\) 都是合法的。

因此考虑一种贪心:

  • 长度最小,因此让 * 尽可能地被替换为空串,即让字符串中原有的 () 尽可能互相匹配。

  • 使用双端队列 \(t\) 维护 * 的下标,栈 \(s\) 维护未匹配的 ( 的下标。

    先扫一遍字符串,将所有 * 的下标加入 \(t\)

    则在扫字符串的时候,

    • 遇到 ( 就将其下标加入栈 \(s\)

    • 遇到 * 直接跳过。

    • 遇到 ) 时,

      • 如果 \(s\) 中还有未匹配的 (,直接匹配最好,即将 \(s\) 的栈顶出栈。

      • 否则,需要动用 * 来保证字符串的合法性。使用最左边的即可,因为使用更靠右的 * 有可能在 ) 的右边。

        也就是说,如果 \(t\) 的队首在 ) 的右边,则无解

    • 扫完之后,\(s\) 中可能还有没匹配的 (,同理使用 \(t\) 的队尾匹配即可。

AC 代码

//#include<bits/stdc++.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<string>
#include<vector>
#include<cmath>
#include<ctime>
#include<deque>
#include<queue>
#include<stack>
#include<list>
using namespace std;
string a;
vector<int>s;
deque<int>t;
int main(){
	/*freopen("test.in","r",stdin);
	freopen("test.out","w",stdout);*/
	
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	
	cin>>a;
	for(int i=0;i<a.size();i++){
		if(a[i]=='*'){
			t.push_back(i);
		}
	}
	for(int i=0;i<a.size();i++){
		if(a[i]=='('){
			s.push_back(i);
		}else if(a[i]==')'){
			if(s.size()){
				s.pop_back();
			}else{
				if(t.size()&&t.front()<i){
					a[t.front()]='(';
					t.pop_front();
				}else{
					cout<<"No solution!\n";
					return 0;
				}
			}
		}
	}
	while(s.size()){
		if(s.back()>=t.back()){
			cout<<"No solution!\n";
			return 0;
		}
		a[t.back()]=')';
		t.pop_back();s.pop_back();	
	} 
	for(char i:a){
		if(i!='*'){
			cout<<i;
		}
	}
	
	cout.flush();
	
	/*fclose(stdin);
	fclose(stdout);*/
	return 0;
}
posted @ 2025-07-21 22:14  TH911  阅读(5)  评论(0)    收藏  举报