最长公共子序列-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数。

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