Codeforces Round #551 (Div. 2)
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){//貪心思想:將前面'?'全部置為'(' 後面'?'全部置為'(',則能夠匹配;需要計算前多少個'?'置(,後多少個'?'置')'。 8if(s.size()%2 != 0){// 中間有奇數個符號,不可能構成 匹配的括號 9return ":("; 10} 11else{ 12int n1=0,n2=0; 13for(int i=0;i<s.size();i++){ 14if(s[i]=='('){//統計 已經有的 ( 數量 15n1++; 16} 17else if(s[i]==')'){//Ditto 18n2++; 19} 20} 21n1 = s.size()/2 - n1;//計算需要前多少個 ? 轉變成 ( 22n2 = s.size()/2 - n2;//Ditto 23int k=0; 24for(int i=0;i<n1;){//將前 n1 個 ? 替換成 ( 25if(s[k++]=='?'){ 26s[k-1]='('; 27i++; 28} 29} 30for(int i=0;i<n2;){//Ditto 31if(s[k++]=='?'){ 32s[k-1]=')'; 33i++; 34} 35} 36int t=0;//驗證是否匹配 37for(int i=0;i<s.size();i++){ 38if(s[i]=='('){ 39t++; 40} 41else{ 42t--; 43} 44if(t<0){//出現 ) 無法匹配到 ( 的情況 45return ":("; 46} 47} 48if(t==0){ 49return "("+s+")"; 50} 51else{ 52return ":("; 53} 54} 55 } 56 string solve(string s){//破壞字首,保證結果不會有字首匹配,取出的中間字串只需要保證能夠構成括號匹配 57if(s[0]==')' || s[s.size()-1]=='(' || s.size()==1){//不符合題意的情況 58return ":("; 59} 60else if(s.size()==0){//符合題意,但是結果是是空 61return ""; 62} 63else{ 64string str(s,1,s.size()-2);//對從第二個到倒數第二個經行處理 65return ps(str);//求解中間字串能否構成括號匹配 66} 67 } 68 int main() 69 { 70string line; 71int n; 72cin>>n; 73getchar(); 74getline(cin,line); 75cout<<solve(line)<<endl; 76return 0; 77 }