動態規劃求最長公用子序列問題

來源:互聯網
上載者:User

標籤:

#include<iostream>#include<string>#include<vector>using namespace std;//找兩個子串str1,str2的最長公用子串substrvoid findLongestSubString(string &str1, string &str2, string &substr){if (str1.empty() || str2.empty()){return;}//定義二維數組lengt[str.size() + 1][str2.size() + 1]來儲存最長公用子串的長度vector<vector<int> > length(str1.size() + 1, vector<int> (str2.size() + 1, 0) );//定義搜尋狀態二維數組state[str.size() + 1][str2.size() + 1],為了後面尋找最長公用子串元素vector<vector<int> > state(str1.size() + 1, vector<int> (str2.size() + 1, 0) );//下面就是運用動態規劃求最長公用子串for(size_t i = 1; i <= str1.size(); i++){for(size_t j = 1; j <= str2.size(); j++){if(str1[i - 1] == str2[j - 1]){length[i][j] = 1 + length[i -1][j - 1];state[i][j] = 1;}else{length[i][j] = (length[i-1][j] >= length[i][j-1] ? length[i-1][j] : length[i][j-1]);if (length[i-1][j] >= length[i][j-1]){state[i][j] = 2;}else{state[i][j] = 3;}}}}for (size_t i = str1.size(), j = str2.size(); i > 0 && j > 0;){if (state[i][j] == 1){substr.push_back(str1[i-1]);i--;j--;}else if (state[i][j] == 2){i--;}else {j--;}}return;}//翻轉字串void reverseString(string &str){if (str.empty()){return;}for (size_t i = 0, j = str.size() - 1; i < j; i++, j--){str[i] = str[i] ^ str[j];str[j] = str[j] ^ str[i];str[i] = str[j] ^ str[i];}return;}int main(void){string str1, str2, substr;//輸入字串str1,str2cin >> str1 >> str2;findLongestSubString(str1, str2, substr);reverseString(substr);cout << "string 1: " << str1 << endl << "string 2: " << str2 << endl << "substring: " << substr << endl;return 0;}

給定字串X=(X1,X2,...,Xm),Y= (Y1,Y2,...,Yn)。求字串X和Y的最長公用子序列。

首先分析字串X和Y的最後一個字元Xm和Yn:

1、如果Xm == Yn,那麼Xm一定是字串X和Y的最長公用子串中的最後一個元素。接下來只要分別求X的前m-1個元素組成的子串(X1,X2,...,Xm-1)和Y的前n-1個元素組成的子串(Y1,Y2,...,Yn-1)的最長公用子串。

2、如果Xm != Yn,那麼X和Y的最長公用子串要麼是(X1,X2,...,Xm)與(Y1,Y2,...,Yn-1)的最長公用子串;要麼是(X1,X2,...,Xm-1)與(Y1,Y2,...,Yn)的最長公用子串。兩者中選長度較長的。


下面列遞推方程:

設length[ i ][ j ]表示字串X的前i個字元與字串Y的前j個字元的最長公用子串的長度。那麼有上面的分析我們有:

length[0][0] = length[0][j] = length[i][0] = 0;   (1 <= i <= m, 1 <= j <= n)

if (Xi == Yj)           length[ i ][ j ] = length [i - 1][j - 1] + 1;           (i >= 1, j>=1)

if (Xi != Yj)      length[ i ][ j ] = max(length[ i - 1][ j ], lenght[ i ][j - 1]);                    (i >= 1, j >= 1)


同時為了得到序列X和Y的最長公用子序列,設二維表state[m+1][n+1],其中state[i][j]表示在計算length[i][j]的過程中的搜尋狀態:


  if(Xi == Yj)        state[i][j] = 1         //說明X的前i個元素和Y的前j個元素的最長公用子序列包含Xi,也就是X和Y的最長公用子序列包含Xi

if(Xi != Yj && length[i - 1][j] >= length[i][j - 1])state[i][j] = 2;           //說明X的前i個元素和Y的前j個元素的最長公用子序列是由X的前i-1個元素和Y的前j個元素的最長公用子序列得到的。同時說明他們的最長公用子序列中不包含元素Xi。

if(Xi != Yj && length[i - 1][j] < length[i][j - 1]) state[i][j ] = 3; //說明X的前i個元素和Y的前j個元素的最長公用子序列是由X的前i個元素和Y的前j-1個元素的最長公用子序列得到的。同時說明他們的最長公用子序列中不包含元素Yj。


那麼在用狀態表搜尋最長公用子序列時,如果state[i][j] == 1,表明Xi = Yj,元素Xi為最長公用子序列的元素,將這個元素存入子串中。下一個搜尋方向為state[i - 1][ j - 1]。

如果state[i][j] == 2,表明Xi != Yj,length[i - 1][j] >= length[i][j - 1],並且最長公用子序列的元素在X的前i-1和Y的前j個元素的最長公用子序列中,那麼繼續搜素state[i-1][j]。

同理如果state[i][j] == 3,表明Xi != Yj,length[i - 1][j] < length[i][j - 1],那麼繼續搜素state[i][j - 1]。




動態規劃求最長公用子序列問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.