最多01子序列問題
阿新 • • 發佈:2018-12-16
01子序列問題
問題描述
給定 n 個二進位制字串,要求調整字串順序並連線所有的字串,使最後得到的字串中有儘可能多的“01”子序列。輸出“01”子序列的最大個數。 (1 ≤ n ≤ 100000)。
解題思路與演算法思想
我們先將字串分成四類
開頭是0結尾是1記為01
同理
四類字串
01
00
11
10
之後我們會發現只有10這種字串是可以連續連線的,因為可以保證最前面是0,
我放上了10之後在前端形成了一個01字串並且在後面又出現了一個0
而01的字串對於形成多餘的另一序列沒有任何作用
00和11可以成對的拼接成為10字串
剩下的邊角料也沒有什麼作用
程式模型的建立
- 選擇一個00作為開頭
- 之後加上10和拼接而成的10
- 最後以11結尾
- 再加上邊角料
資料結構的選用
- vector
- string
程式設計流程
- 儲存
- 分類
- 填充
程式設計偽碼演算法
while(a10.size()!=0) { sum.push_back(a10[a10.size()-1]) ; a10.pop_back() ; } //之後看0_1 int c = min(a0.size(),a11.size()) ; for(int i = 0 ;i<c ;i++) { sum.push_back(a11[a11.size()-1]) ; a11.pop_back() ; sum.push_back(a0[a0.size()-1]) ; a0.pop_back() ; } c = min(a1.size(),a00.size()) ; for(int i = 0 ; i<c ;i++) { sum.push_back(a00[a00.size()-1]) ; a00.pop_back() ; sum.push_back(a1[a1.size()-1]) ; a1.pop_back() ; } //合成00 11 c = min(a00.size(),a11.size()) ; for(int i = 0 ;i<c ;i++) { sum.push_back(a00[a00.size()-1]) ; a00.pop_back() ; sum.push_back(a11[a11.size()-1]) ; a11.pop_back() ; }
源程式編碼清單
#include<iostream> #include<vector> #include<string> #include<algorithm> using namespace std ; int main(void) { vector<string>sum ; vector<string>a00 ; vector<string>a11 ; vector<string>a01 ; vector<string>a10 ; vector<string>a0 ; vector<string>a1 ; int n ; scanf("%d",&n) ; for(int i = 0 ; i<n ;i++) { string tem ; cin>>tem ; if(tem.size()==1) { if(tem[0]== '0') { a0.push_back(tem) ; //cout<<"dsakd;salkdls;kdl;askdl;ksal;dka;s"<<endl; } if(tem[0] =='1') { a1.push_back(tem) ; } } else { //cout<<"int lese"<<endl ; // cout<<"akjksa"<<*tem.begin()<<endl ; // cout<<"askdjkks"<<tem[tem.size()-1]<<endl ; if((tem[0]=='0')&&(tem[tem.size()-1]=='1')) { a01.push_back(tem) ; } if((tem[0]=='1')&&(tem[tem.size()-1]=='1')) { a11.push_back(tem) ; } if((tem[0]=='0')&&(tem[tem.size()-1]=='0')) { a00.push_back(tem) ; } if((tem[0]=='1')&&(tem[tem.size()-1]=='0')) { a10.push_back(tem) ; //cout<<"here !"<<endl ; } } } //cout<<"sdkaldj"<<endl ; //先看開頭,如果都沒有那也沒有辦法 if(a00.size()!=0) { sum.push_back(a00[a00.size()-1]) ; a00.pop_back() ; } else { if(a0.size()!=0) { sum.push_back(a0[a0.size()-1]) ; a0.pop_back() ; } } //內部 //先將1——0放進去 while(a10.size()!=0) { sum.push_back(a10[a10.size()-1]) ; a10.pop_back() ; } //之後看0_1 int c = min(a0.size(),a11.size()) ; for(int i = 0 ;i<c ;i++) { sum.push_back(a11[a11.size()-1]) ; a11.pop_back() ; sum.push_back(a0[a0.size()-1]) ; a0.pop_back() ; } c = min(a1.size(),a00.size()) ; for(int i = 0 ; i<c ;i++) { sum.push_back(a00[a00.size()-1]) ; a00.pop_back() ; sum.push_back(a1[a1.size()-1]) ; a1.pop_back() ; } //合成00 11 c = min(a00.size(),a11.size()) ; for(int i = 0 ;i<c ;i++) { sum.push_back(a00[a00.size()-1]) ; a00.pop_back() ; sum.push_back(a11[a11.size()-1]) ; a11.pop_back() ; } //加上邊角料 while(a0.size()!=0) { sum.push_back(a0[a0.size()-1]) ; a0.pop_back() ; } while(a1.size()!=0) { sum.push_back(a1[a1.size()-1]) ; a1.pop_back() ; } while(a11.size()!=0) { sum.push_back(a11[a11.size()-1]) ; a11.pop_back() ; } while(a10.size()!=0) { sum.push_back(a10[a10.size()-1]) ; a10.pop_back() ; } while(a01.size()!=0) { sum.push_back(a01[a01.size()-1]) ; a01.pop_back() ; } while(a00.size()!=0) { sum.push_back(a00[a00.size()-1]) ; a00.pop_back() ; } // cout<<"sdkaldj"<<endl ; string sum1 ; string temc ; temc.push_back(0) ; temc.push_back(1) ; int cnt = 0 ; //數出來個數 //cout<<sum.size() ; for(int i = 0 ; i <sum.size() ;i++) { //cout<<sum[i]<<endl ; } for(int i = 0 ;i<sum.size() ;i++) { sum1+=sum[i] ; } cout<<sum1<<endl ; // cout<<"sdkaldj"<<endl ; for(int i = 0 ;i<sum1.size() ;i++) { if(sum1[i]=='0'&&sum1[i+1]=='1') { cnt++ ; } } printf("%d\n",cnt) ; }
程式輸入、輸出
輸入:
3
00
11
01
輸出
001011
2
輸入輸出檔案或程式執行結果截圖
時間與空間複雜度分析
空間複雜度:
n^2
程式使用說明
總結與完善