DP问题之最长公共子序列

问题描述:给定两个序列X=<x1, x2,x3,…,xm> 和 Y=<y1, y2, y3,…, yn>, 求X与Y的一个最长公共子序列

 

问题分析:这个题目的阶段不是明显,没有很明显的上一步、上一层之类的。

既然涉及到公共子序列,也就是有X的第 i 个字符和Y的第 j 个字符相等的情况。

显然如果X[i] = Y[j] 那么长度分别为 i 和 j 的最长公共子序列就是长度分别为 i-1 和 j-1的最长公共子序列 加上 X[i] 或 Y[j]。

如果X[i] != Y[j] 呢?

如果不相等,那么长度为 i 和长度为 j 的序列的最长公共子序列就是“长度为i-1 和 j ” 和“长度为 i 和 j-1 ”中最长公共子序列中较长的一个

因此可以设计以一个状态opt[i, j] 表示起点为 1 ,长度分别为 i 和 j 的最长公共子序列,状态方程可以写为:

                      opt[i-1, j-1] + x[i]     x[i]  == y[j]

opt[i, j] =      opt[i-1, j]                   x[i]   != y[j] && Len(opt[i-1, j] ) >= Len(opt[i, j-1])

                      opt[i, j-1]                   x[i]   != y[j] && Len(opt[i-1, j])  < Len(opt[i, j-1]) 

(0 <= i <= Len(X) && 0 <= j <= Len(Y))

 

测试代码:

#include <stdio.h>

#include <stdlib.h>



static const int m = 8;

static const int n = 6;

char X[8] = {' ','A','B','C','B','D','A','B'}; //X[0] 为了后面写代码方便 

char Y[6] = {' ','B','D','C','B','A'};



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;

}
 
结果:
Longest Common Sequence Length: 4

B C B A

请按任意键继续. . .

你可能感兴趣的:(dp)