1. 程式人生 > >【經典動態規劃問題】最長公共子序列LCS

【經典動態規劃問題】最長公共子序列LCS

目錄

題目

題目分析

狀態

邊界值討論

其他情況討論

程式碼實現


從題目出發分析如何用動態規劃求解最長公共子序列問題

題目

給定兩個字串A和B,返回兩個字串的最長公共子序列的長度。例如,A="1A2C3D4B56”,B="B1D23CA45B6A”,”123456"或者"12C4B6"都是最長公共子序列。

給定兩個字串AB,同時給定兩個串的長度nm,請返回最長公共子序列的長度。保證兩串長度均小於等於300。

測試樣例:

"1A2C3D4B56",10,"B1D23CA45B6A",12
返回:6

題目分析

狀態

dp[i][j],表示A[0,...i]和B[0,...j]的最長公共子序列長度。

邊界值討論

當i = 0時,dp[i][j]求的是A[0]和B[0,...j]的最長公共子序列長度,遍歷B陣列,如B[k] == A[0],也就是在B中找到了等於A[0]的值,最長公共子序列就是A[0],則dp[0][k,k+1,...m] = 1;

同理,當j = 0時,dp[i][j]求的是A[0,...i]和B[0]的最長公共子序列長度,遍歷A陣列,如A[t] == B[0],最長公共子序列就是B[0],則dp[t,t+1,...n][0] = 1;

其他情況討論

求一般情況下的dp[i][j],只可能出現兩種情況:

1.如果A[i] == B[j],dp[i][j] = dp[i-1][j-1]+1; 如‘ABCD’和‘ABDD’的最長公共子序列長度等於‘ABC’和‘ABD’的最長公共子序列長度+1,因為末尾元素D一定會包含在'ABCD'和'ABDD'的最長公共子序列中。

2.如果A[i]!=B[j],那麼,A[0,...i]和B[0,...j]的最長公共子序列要麼從A[0,..i]和B[0,...j-1]中取得,要麼從A[0,..i-1]和B[0,...j]中取得;比較兩個值中的最大值,即為dp[i][j]的值;如‘ABCD’和‘ABD4’中最長公共子序列的長度等於‘ABC’和‘ABD4'的最長公共子序列長度,要麼等於‘ABCD’和‘ABD’的最長公共子序列長度,我們只需要取最大值即可。

程式碼實現

class LCS {
public:
    int findLCS(string A, int n, string B, int m) {
        // write code here
       //dp[i][j]表示A[0,...i]和B[0,...j]的最長公共子序列的長度
        int dp[301][301] = {0};
   for(int i = 0;i<n;i++){//第一列中,找出A[i] = B[0],dp[i][0] = 1,且dp[i+1,...n][0] = 1;
    
       if(A[i]==B[0]) //
       {
           for(int j = i;j<n;j++){
               dp[j][0] = 1;
           }
       }
   }
       
      for(int i = 0;i<m;i++){//第一行中,找出A[0] = B[i],dp[0][i] = 1,且dp[0][i+1,...m] = 1;
    
       if(A[0]==B[i]) //
       {
           for(int j = i;j<m;j++){
               dp[0][j] = 1;
           }
       }
   }
   //接下來考慮一般情況,dp[i][j]可能來自哪些情況:
      // A[i] != B[j] ,A[0...i]和B [0,...j-1]的最長公共子序列為dp[i][j-1]
     //如果A[i] == B[j],dp[i][j] = dp[i-1][j-1]+1
     // A[i] != B[j] ,A[0...i-1]和B [0,...j]的最長公共子序列為dp[i-1][j]
   int max = 0;
   for(int i = 1;i<n;i++){
       for(int j = 1;j<m;j++){
           if(A[i] == B[j])
               max= dp[i-1][j-1]+1;
           else{
               max = (dp[i][j-1] > dp[i-1][j] ? dp[i][j-1]: dp[i-1][j]);
           }
           dp[i][j] = max;
            
       }
   }
    return dp[n-1][m-1];
    }
};