C. Serval and Parenthesis Sequence
题源:
http://codeforces.com/contest/1153/problem/C
题意:
给定一个长度为 n 的, 只包含'(' , ')' 和 '?' 三种字符的字符串, 问该串是否能够成 任意前缀 都不是括号匹配的 , 但整体是括号匹配的字符串, 若是则输出任意一种这种字符串, 否者输出 ":(".
思路:
单独判断一个含有 未定括号 的字符串是否是 括号匹配的 字符串, 可以用贪心的思想来处理. 如果是一个括号字符串是括号匹配的, 那么一定是 "前面" 有一半的 '(' ,"后面" 有一半是')'. 于是可以将 "前面" 若干个 '?' 变成 '(' ,"后面" 若干个 '?' 变成 ')' , 构成 "前面" 一半是 '(' ,"后面" 一半是')', 满足这个必要性的括号匹配字符串. 问题的关键就变成了 -- 确定前多少个 '?' 应该变成 '(', 后多少个 '?' 变成 ')' .
任意前缀都不是括号匹配的导致无法直接按照上面的思路来处理. 但是这个约束条件等于直接限定了符合题意的字符串开头必须要能表示为 '(' , 字符串的结尾要能表示为 ')' . 所以可以将首字符和尾字符拿掉, 保证中间字符是括号匹配的即可.
代码:
- #include<cstdio>
- #include<string>
- #include<iostream>
- using namespace std; 7 string ps(string s){ // 贪心思想: 将前面'?'全部置为'(' 后面'?'全部置为'(', 则能够匹配; 需要计算前多少个'?'置 (, 后多少个'?'置')'.
- if(s.size()%2 != 0){ // 中间有奇数个符号, 不可能构成 匹配的括号
- return ":(";
- }
- else{
- int n1=0,n2=0;
- for(int i=0;i<s.size();i++){
- if(s[i]=='('){ // 统计 已经有的 ( 数量
- n1++;
- }
- else if(s[i]==')'){ //Ditto
- n2++;
- }
- }
- n1 = s.size()/2 - n1; // 计算需要前多少个 ? 转变成 (
- n2 = s.size()/2 - n2; //Ditto
- int k=0;
- for(int i=0;i<n1;){ // 将前 n1 个 ? 替换成 (
- if(s[k++]=='?'){
- s[k-1]='(';
- i++;
- }
- }
- for(int i=0;i<n2;){ //Ditto
- if(s[k++]=='?'){
- s[k-1]=')';
- i++;
- }
- }
- int t=0; // 验证是否匹配
- for(int i=0;i<s.size();i++){
- if(s[i]=='('){
- t++;
- }
- else{
- t--;
- }
- if(t<0){ // 出现 ) 无法匹配到 ( 的情况
- return ":(";
- }
- }
- if(t==0){
- return "("+s+")";
- }
- else{
- return ":(";
- }
- }
- }
- string solve(string s){ // 破坏前缀, 保证结果不会有前缀匹配, 取出的中间字符串只需要保证能够构成括号匹配
- if(s[0]==')' || s[s.size()-1]=='(' || s.size()==1){ // 不符合题意的情况
- return ":(";
- }
- else if(s.size()==0){ // 符合题意, 但是结果是是空
- return "";
- }
- else{
- string str(s,1,s.size()-2); // 对从第二个到倒数第二个经行处理
- return ps(str); // 求解中间字符串能否构成括号匹配
- }
- }
- int main()
- {
- string line;
- int n;
- cin>>n;
- getchar();
- getline(cin,line);
- cout<<solve(line)<<endl;
- return 0;
- }
来源: https://www.cnblogs.com/11235yuan/p/10714331.html