Codeforces Round #551 (Div. 2)
阿新 • • 發佈:2019-04-16
問題 getline 輸出 ali for 取出 style nth 單獨
C. Serval and Parenthesis Sequence
題源:
http://codeforces.com/contest/1153/problem/C
題意:
給定一個長度為n的,只包含‘(‘ , ‘)‘ 和 ‘?‘ 三種字符的字符串,問該串是否能夠成 任意前綴 都不是括號匹配的 ,但整體是括號匹配的字符串,若是則輸出任意一種這種字符串,否者輸出 ":("。
思路:
單獨判斷一個含有 未定括號 的字符串是否是 括號匹配的 字符串,可以用貪心的思想來處理。如果是一個括號字符串是括號匹配的,那麽一定是“前面”有一半的 ‘(‘ ,“後面”有一半是‘)‘。於是可以將“前面”若幹個 ‘?‘ 變成 ‘(‘ ,“後面”若幹個 ‘?‘ 變成 ‘)‘ ,構成“前面”一半是 ‘(‘ ,“後面”一半是‘)‘,滿足這個必要性的括號匹配字符串。問題的關鍵就變成了——確定前多少個 ‘?‘ 應該變成 ‘(‘,後多少個 ‘?‘ 變成 ‘)‘ 。
任意前綴都不是括號匹配的導致無法直接按照上面的思路來處理。但是這個約束條件等於直接限定了符合題意的字符串開頭必須要能表示為 ‘(‘ , 字符串的結尾要能表示為 ‘)‘ 。所以可以將首字符和尾字符拿掉,保證中間字符是括號匹配的即可。
代碼:
1 #include<cstdio> 2 #include<string> 3 #include<iostream> 5 using namespace std; 7 string ps(string s){ //貪心思想:將前面‘?‘全部置為‘(‘ 後面‘?‘全部置為‘(‘,則能夠匹配;需要計算前多少個‘?‘置(,後多少個‘?‘置‘)‘。8 if(s.size()%2 != 0){ // 中間有奇數個符號,不可能構成 匹配的括號 9 return ":("; 10 } 11 else{ 12 int n1=0,n2=0; 13 for(int i=0;i<s.size();i++){ 14 if(s[i]==‘(‘){ //統計 已經有的 ( 數量 15 n1++; 16 } 17 else if(s[i]==‘)‘){ //Ditto 18 n2++; 19 } 20 } 21 n1 = s.size()/2 - n1; //計算需要前多少個 ? 轉變成 ( 22 n2 = s.size()/2 - n2; //Ditto 23 int k=0; 24 for(int i=0;i<n1;){ //將前 n1 個 ? 替換成 ( 25 if(s[k++]==‘?‘){ 26 s[k-1]=‘(‘; 27 i++; 28 } 29 } 30 for(int i=0;i<n2;){ //Ditto 31 if(s[k++]==‘?‘){ 32 s[k-1]=‘)‘; 33 i++; 34 } 35 } 36 int t=0; //驗證是否匹配 37 for(int i=0;i<s.size();i++){ 38 if(s[i]==‘(‘){ 39 t++; 40 } 41 else{ 42 t--; 43 } 44 if(t<0){ //出現 ) 無法匹配到 ( 的情況 45 return ":("; 46 } 47 } 48 if(t==0){ 49 return "("+s+")"; 50 } 51 else{ 52 return ":("; 53 } 54 } 55 } 56 string solve(string s){ //破壞前綴,保證結果不會有前綴匹配,取出的中間字符串只需要保證能夠構成括號匹配 57 if(s[0]==‘)‘ || s[s.size()-1]==‘(‘ || s.size()==1){ //不符合題意的情況 58 return ":("; 59 } 60 else if(s.size()==0){ //符合題意,但是結果是是空 61 return ""; 62 } 63 else{ 64 string str(s,1,s.size()-2); //對從第二個到倒數第二個經行處理 65 return ps(str); //求解中間字符串能否構成括號匹配 66 } 67 } 68 int main() 69 { 70 string line; 71 int n; 72 cin>>n; 73 getchar(); 74 getline(cin,line); 75 cout<<solve(line)<<endl; 76 return 0; 77 }
Codeforces Round #551 (Div. 2)