最长公共子序列

来源:互联网 发布:男士护肤吧 淘宝店铺 编辑:程序博客网 时间:2024/06/05 06:37

一、最长公共子序列算法基本思想

最长公共子序列是基于动态规划的思想。

最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。而最长公共子串(要求连续)和最长公共子序列是不同的(摘自百度百科)

我们可以分三个方面思考这样个问题:

1.如果x序列的最后一个元素和y序列的最后一个元素相同,那么这个元素必定是最长公共子序列的最后一个元素。

2.如果x序列和y序列的最后一个元素不同,那么问题就推给除了最后一个元素的x序列和完整y序列这两个序列的最长公共子序列(记为A),以及完整的x序列和除了最后一个元素的y序列这两个序列的最长公共子序列(记为B),max{A,B}就是原问题的解。

3.重复2步骤,递归下去,一直到x序列为空,或者y序列为空。

二、最长公共子序列的数据结构

c[i][j] 二维数组: 表示x从1到i的子序列和y从1到j的子序列的最长公共子序列。

b[i][j] 二维数组:表示x从1到i的子序列和y从1到j的子序列的最长公共子序列是由哪种情况下获得的。

value 1: 表示当xi == yi 字符的时候获得一个最长公共子序列的元素

value 2: 表示问题推给了x[1...i-1] 和 y[1...j]的最长公共子序列

value 3: 表示问题推给了x[1...i] 和 y[1...j-1]的最长公共子序列

三、最长公共子序列过程图解


四、算法源代码

#include <cstdio>//序列x以及x的长度,字符串前面的空格是来填充的//好让字符串首字母从下标1开始char x[] = " ABCBDAB";int lenx = 7;//序列y以及y的长度char y[] = " BDCABA";int leny = 6;//c[i][j]表示长度为i的x序列//和长度为j的y序列的最大公共子序列int c[8][7];//记录c[i][j]的值是由哪个子问题产生的int b[8][7];//计算最长公共子序列的函数//并且记录了最长公共子序列int lcsLength();//构建最长公共子序列void lcs(int i, int j);int main(){    printf("%d\n",lcsLength());    lcs(lenx, leny);    return 0;}int lcsLength(){    //如果x为空序列那么无论y取多长,x,y的最大公共子序列一定为0    for (int i = 1; i<=lenx; i++) c[i][0] = 0;    //如果y为空序列那么无论x取多长,x,y的最大公共子序列一定为0    for (int i = 1; i<=leny; i++) c[0][i] = 0;    for (int i=1;i<=lenx;i++){        for (int j=1; j<=leny; j++) {            //如果长度为i的x序列和长度为j的y序列的最后一个字符相同            //那么最大公共子序列就是c[i-1][j-1]+1            if(x[i] == y[j]){                c[i][j] = c[i-1][j-1]+1;                b[i][j] = 1;    //用1标记表示长度为i的x序列                                //长度为j的y序列中最后一个字符是相同的                                            //如果不等那么c[i][j] = max{c[i-1][j] , c[i][j-1]}            }else if(c[i-1][j]>=c[i][j-1]){                c[i][j] = c[i-1][j];                b[i][j] = 2;            }else{                c[i][j] = c[i][j-1];                b[i][j] = 3;            }        }    }    return  c[lenx][leny];}//通过b数组记录的信息构建最长公共子序列void lcs(int i,int j){    if(i==0||j==0)        return;    if (b[i][j] == 1) {        lcs(i-1,j-1);        printf("%c",x[i]);    }else if(b[i][j] == 2){        lcs(i-1,j);    }else{        lcs(i,j-1);    }}


0 0