最长公共子序列的长度(动态规划)解决方案
最长公共子序列的长度(动态规划)
给定X = 3, 0, 3, 8, 4, 4
Y= 4, 3, 8, 3, 0, 4
求X和Y的最长公共子序列的长度。
------解决方案--------------------
int len[8][6] = {0}; //记录序列1的 i 和序列2的 j 的最长公共子序列的长度
int flag[8][6] = {0}; //记录在i和j处的选择,为后面输出最长子序列
int LCS()
{
int i, j;
for(i=1; i<m; i++)
{
for(j=1; j<n; j++)
{
if(X[i] == Y[j])
{
len[i][j] = len[i-1][j-1] + 1;
flag[i][j] = 0;
}
else if(len[i-1][j] >= len[i][j-1])
{
len[i][j] = len[i-1][j];
flag[i][j] = 1;
}
else
{
len[i][j] = len[i][j-1];
flag[i][j] = 2;
}
}
}
return len[m-1][n-1];
}
void printLCS(int i, int j)
{
if(i==0
------解决方案--------------------
j==0)
return;
if(flag[i][j] == 0)
{
printLCS(i-1, j-1);
printf("%c ", X[i]);
}
else
{
if(flag[i][j] == 1)
printLCS(i-1, j);
else
printLCS(i, j-1);
}
}
int main()
{
printf("Longest Common Sequence Length: %d\n", LCS());
printLCS(m-1, n-1);
printf("\n");
return 0;
}
------解决方案--------------------
DP主要就是一个递推公式。
其实现还是比较简单的,填表法,需要记录解的过程,这样才能在之后找到解。
给定X = 3, 0, 3, 8, 4, 4
Y= 4, 3, 8, 3, 0, 4
求X和Y的最长公共子序列的长度。
------解决方案--------------------
int len[8][6] = {0}; //记录序列1的 i 和序列2的 j 的最长公共子序列的长度
int flag[8][6] = {0}; //记录在i和j处的选择,为后面输出最长子序列
int LCS()
{
int i, j;
for(i=1; i<m; i++)
{
for(j=1; j<n; j++)
{
if(X[i] == Y[j])
{
len[i][j] = len[i-1][j-1] + 1;
flag[i][j] = 0;
}
else if(len[i-1][j] >= len[i][j-1])
{
len[i][j] = len[i-1][j];
flag[i][j] = 1;
}
else
{
len[i][j] = len[i][j-1];
flag[i][j] = 2;
}
}
}
return len[m-1][n-1];
}
void printLCS(int i, int j)
{
if(i==0
------解决方案--------------------
j==0)
return;
if(flag[i][j] == 0)
{
printLCS(i-1, j-1);
printf("%c ", X[i]);
}
else
{
if(flag[i][j] == 1)
printLCS(i-1, j);
else
printLCS(i, j-1);
}
}
int main()
{
printf("Longest Common Sequence Length: %d\n", LCS());
printLCS(m-1, n-1);
printf("\n");
return 0;
}
------解决方案--------------------
DP主要就是一个递推公式。
其实现还是比较简单的,填表法,需要记录解的过程,这样才能在之后找到解。
#include <iostream>
#include <string>
#include <stack>
using namespace std;
/*
DP的核心公式:
if xi = yj:
LCS(xi,yj)=LCS(xi-1,yj-1)+1;
else
LCS(xi,yj)=max(LCS(xi-1,yj),LCS(xi,yj-1)).
*/
int LCS_DP( string x, string y )
{
int xlen=x.size();
int ylen=y.size();
//int *lcs = new int[(xlen+1)*(ylen+1)]();
int **lcs = new int*[xlen+1];
int **path = new int*[xlen+1];
for( int i=0; i<=xlen; i++){
lcs[i] = new int[ylen+1]();
path[i] = new int[ylen+1]();
}
for( int k=1; k<=xlen+ylen;k++){
for( int i=1; i<=xlen; i++){
for( int j=1; j<=k-i&&j<=ylen; j++){
if(x[i-1]==y[j-1]){
lcs[i][j] = lcs[i-1][j-1]+1;
path[i][j] = 1; //1表示两个字符相等
}
else{
int a=lcs[i-1][j];
int b=lcs[i][j-1];
lcs[i][j] = a>b?a:b;
path[i][j] = a>b?2:3; //2表示来自y,3表示来自x
}
}
}
}
stack<char> stk;
for( int i=xlen,j=ylen; i>0&&j>0; )
{
if( path[i][j] == 1 ){
stk.push( x[i-1] );
i--;j--;
}
if( path[i][j] == 2 ){
i--;
}
if( path[i][j] == 3 ){
j--;
}
}
cout <<"The Longest Common Sequence Length: " <<lcs[xlen][ylen]<<endl;
cout <<"The Longest Common Sequence is:"<<endl;