最长公共子序列(动态规划)

最长公共子序列(动态规划)

图片以及参考来源
最长公共子序列:LCS(Longest common subsequence)

设X={X1,X2,X3,X4…,Xm},Y={Y1,Y2,Y3,Y4…,Yn},Z={Z1,Z2,Z3,Z4…,Zk}是他们的最长公共子序列

分析可知:

1、如果Xm = Yn,则Zk = Xm = Yn 且 Zk-1是Xm-1和Yn-1的LCS

2、如果Xm != Yn 且 zk != xm,则Z是Xm-1和Y的一个LCS

3、如果Xm != Yn 且 zk != yn,则Z是X和Yn-1的一个LCS

用二维数组c存x,y的最长公共子序列,二维数组b存值的来源。
图片是抄的,链接放文章开头了
我们假设二维数组c的横坐标为序列x,纵坐标为序列y,且都有一个第0列和第0行,因为空序列与任何序列都为空。
c[2][4]=1的含义是序列x的子序列AB 与 序列y的子序列BDCA最长公共子序列=1.
图片是抄的,链接放文章开头了

#include <string.h>
#include <iostream>
using namespace std;

#define MAXSIZE 100

int c[MAXSIZE][MAXSIZE];	//二维数组c存两个序列最大公共子序列中元素个数
int b[MAXSIZE][MAXSIZE];	//数组b存两个序列最大公共子序列中元素个数是从哪来的

void LCSLength( int xLength, int yLength, char *x, char *y ) {

    //二维数组c第一列置0
    for( int i = 0; i <= xLength; i++ ) {
        c[i][0] = 0;
    }

    //二维数组c第一行置0
    for( int i = 0; i <= yLength; i++ ) {
        c[0][i] = 0;
    }

    //填充表格
    for( int i = 1; i <= xLength; i++ ) {
        for( int j = 1; j <= yLength; j++ ) {

            //这里x与y的下标要减一,因为x,y都是从下标0开始存。而数组c是从1开始表示的
            if( x[i - 1] == y[j - 1] ) {

                //如果对应元素相等,最大值 = 上一个最大子序列+1
                c[i][j] = c[i - 1][j - 1] + 1;
                b[i][j] = 1;	// =1 表示由对角线得
            } else if( c[i - 1][j] >= c[i][j - 1] ) { //不相等时,选c[i - 1][j]与c[i][j - 1] 较大那个
                c[i][j] = c[i - 1][j];
                b[i][j] = 2; //=2 表示由表中上面元素得
            } else {
                c[i][j] = c[i][j - 1];
                b[i][j] = 3; //=3 表示由表中左面元素得
            }
        }
    }
}

//输出最大公共子序列中元素
//递归调用 后进先出
void LCS( int i, int j, char *x ) {
    if( i == 0 || j == 0 ) { //第0行或第0列的无最大子段和
        return ;
    }

    //表格元素由对角线元素得
    if( b[i][j] == 1 ) {
        LCS( i - 1, j - 1, x );
        cout << x[i - 1];
    } else if( b[i][j] == 2 ) {
        LCS( i - 1, j, x );
    } else {
        LCS( i, j - 1, x );
    }
}

int main() {
    char x[MAXSIZE], y[MAXSIZE];
    int xLength ;
    int yLength ;
    cin >> x >> y;
    xLength = strlen( x );
    yLength = strlen( y );
    LCSLength( xLength, yLength, x, y );
    LCS( xLength, yLength, x );

    //for( int i = 0; i <= xLength; i++ ) {
    //    for( int j = 0; j <= yLength; j++ ) {
    //        printf( "\t%d", b[i][j] );
    //    }
    //    cout << endl;
    //}
    /*for( int i = 0; i <= xLength; i++ ) {
        for( int j = 0; j <= yLength; j++ ) {
            printf( "\t%d", c[i][j] );
        }
        cout << endl;
    }*/

    system( "pause" );
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值