有序子序列定義:若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數。