動態規劃之最長01子序列問題
阿新 • • 發佈:2018-12-20
問題描述
- 現在有兩個字串已知
- 要求的他們最長的公共子序列長度
例如csdnblog和belong的最長公共子序列是4,由於它們都含有blog這一個子序列
解題思路與演算法思想
既然使用動態規劃演算法,那麼演算法的核心就是將問題分佈
這一點和數學歸納法有點相似
假設含有字串xc長度為a
有字串y長度為b
現在在比較x的前a1位和y的前b1位置的最長公共子序列
那麼我們需要假設已知之前的所有狀態,如圖:
程式模型的建立
- 先將資料輸入
- 建立轉移方程:
如果當前的兩個字元相同 那麼加一 如果不同 在其他狀態之中選擇一個比較大的
- 之後通過遞迴+記憶的方式計算出匹配的最大字串
- 最後將匹配的個數輸出
資料結構的選用
選用string去儲存這兩個字串
程式設計流程
輸入資料
進行計算
輸出結果
程式設計偽碼演算法
if((c<0)||(d<0)) { return 0 ; } if(bb[c][d]!=-1) { return bb[c][d] ; } if(a[c] == b[d] ) { bb[c][d] = find_num(a,b,c-1,d-1)+1 ; return bb[c][d] ; } else { bb[c][d] = max(find_num(a,b,c-1,d),find_num(a,b,c,d-1)) ; return bb[c][d] ; }
源程式編碼清單
#include<iostream> #include<string> #include<vector> using namespace std ; int find_num(string a ,string b ,int c ,int d) ; vector< vector<int> > bb ; int main(void) { string a ; string b ; vector<int>aa ; cin>>a ; cin>>b ; for(int i = 0 ;i<b.size() ;i++) { aa.push_back(-1) ; } for(int i = 0 ;i<a.size() ;i++) { bb.push_back(aa) ; } printf("%d",find_num(a,b,a.size()-1,b.size()-1)) ; } int find_num(string a ,string b ,int c ,int d) { if((c<0)||(d<0)) { return 0 ; } if(bb[c][d]!=-1) { return bb[c][d] ; } if(a[c] == b[d] ) { bb[c][d] = find_num(a,b,c-1,d-1)+1 ; return bb[c][d] ; } else { bb[c][d] = max(find_num(a,b,c-1,d),find_num(a,b,c,d-1)) ; return bb[c][d] ; } }
程式輸入、輸出
輸入:
csdnblog
belong
輸出:
4
輸入輸出檔案,或程式執行結果截圖
時間與空間複雜度分析
時間複雜度是n^2
程式使用說明
總結與完善