动态规划-最长公共子序列

若给定序列X={x1,x2,…,xm},则另一序列Z={z1,z2,…,zk},是X的子序列是指存在一个严格递增下标序列{i1,i2,…,ik}使得对于所有j=1,2,…,k有:zj=xij。例如,序列Z={B,C,D,B}是序列X={A,B,C,B,D,A,B}的子序列,相应的递增下标序列为{2,3,5,7}。
给定2个序列X和Y,当另一序列Z既是X的子序列又是Y的子序列时,称Z是序列X和Y的公共子序列。
给定2个序列X={x1,x2,…,xm}和Y={y1,y2,…,yn},找出X和Y的最长公共子序列。

m[0...m,0]=0;
m[0,0...n]=0;
if(x[i]==y[j])
    m[i,j]=m[i-1,j-1]+1;
else if m[i,j-1]>=m[i-1,j]
    m[i,j]=m[i,j-1]
else
    m[i,j]=m[i-1,j]
#include <stdio.h>
#include <string.h>
#define MAXLINE 100

//求最长子序列的长度。辅助二维数组b[][]是用来在print函数中输出的
//时候用的
void LCSlength(int n,int m,char *x,char *y,int c[][MAXLINE],int b[][MAXLINE]){
    for(int i=0;i<=n;i++)
        for(int j=0;j<=m;j++){
            if(j==0||i==0)
                c[i][j]=0;
            else
                if(x[i-1]==y[j-1]){
                    c[i][j]=c[i - 1][j - 1]+1;
                    b[i][j]=1;
                }
                else{
                    if(c[i][j-1]>=c[i-1][j])
                    {
                        c[i][j]=c[i][j-1];
                        b[i][j]=2;
                    }
                    else{
                        c[i][j]=c[i-1][j];
                        b[i][j]=3;
                    }
                }
        }
    return;
}

void LCS(int i,int j,int b[][MAXLINE],char *x,char *y){
    if(i==0||j==0) return;
    if(b[i][j]==1)
    {
        LCS(i-1, j-1, b, x, y);
        printf("%c ", x[i-1]);
    }
    else if(b[i][j]==2)
    {
        LCS(i, j-1, b, x, y);
    }
    else{
        LCS(i-1, j, b, x, y);
    }

}

int main() {
    char x[]="ABCBDAB";
    char y[]="BDCABA";
    int n=strlen(x);

    int m=strlen(y);

    int c[MAXLINE][MAXLINE];
    int b[MAXLINE][MAXLINE];
    LCSlength(n, m, x, y, c, b);
    LCS(n, m, b, x, y);

        return 0;
}
点赞