最長公共子序列-DP

有序子序列定義:若X=<X1 , X2 , X3 , X4 , ... , Xn>則它的子序列爲Y=<Xi , Xj , Xk , ... , Xm>,即原序列調出若干項組成的序列且下標要求有序。

LCS(最長公共子序列)定義:給定兩個序列X=<X1 , X2 , X3 , X4 , ... , Xn>和Y=<Y1 , Y2 , Y3 , Y4 , ... , Ym>存在一個嚴格遞增的X的下標序列爲<i1 , i2 , ... , ik>,對所有的j=1,2,3...k,滿足xi=yj,例如X=<1 , 4 , 3 , 2 , 5>,Y=<4 , 3 , 5 , 7>,則X和Y的最長公共子序列爲<4 , 3 , 5>(下標不一定要連續).

題目描述:給定兩個字符串,,輸出他們的最長公共子序列長度。

樣例輸入:

abcfbc abfcab
programming contest
abcd mnp

樣例輸出:

4

2

0

源代碼:

#include<iostream>
#include<cstring>
#define MAX 1001
using namespace std;

int max( int a , int b ){
        return a > b ? a : b; 
}

int  dp[MAX][MAX];
char str1[MAX] , str2[MAX];

int main( ){
    int i , j , len1 , len2;

    while( ~scanf("%s %s",str1, str2) )
    {
        memset( dp , 0 , sizeof( dp ) );

        len1 = strlen( str1 );
        len2 = strlen( str2 );

        for( i=1 ; i<=len1 ; i++ )
            for( j=1 ; j<=len2 ; j++ ){
                if( str1[i-1] == str2[j-1] )
                    dp[i][j] = dp[i-1][j-1] + 1;
                else
                    dp[i][j] = max( dp[i-1][j] , dp[i][j-1] );
            }

        cout<<dp[len1][len2]<<endl;
    }

    return 0;
}
代碼分析:採用動態規劃DP的算法來解決LCS問題再好不過了,DP算法要求問題滿足最優子結構和重複子問題(純DFS算法的缺點便顯而易見了,子問題已經重複做了若干,花費了開銷),不過遵循時空守恆的原則,用了DP你需要開出一個額外的數組,才存儲每個狀態的最優解,下一個最優解是由子問題的最優解運算而成的。也就是說DP需要一個狀態轉移方程,描述了問題與子問題間的遞推關係。該題中轉移方程爲{ if(xi==yj)dp[i][j]=dp[i-1][j-1]+1;  if( xi!=yj )  dp[i][j]=max(dp[i-1][j] , dp[i][j-1]) },其中dp[i][j]的含義是第一字符串前i個子字符串和第二個字符串的前j個子字符串形成的LCS數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章