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

来源:互联网 发布:it培训招生计划 编辑:程序博客网 时间:2024/06/05 08:44

一.基本概念

最长公共子串:子串在原字符串中是最长且连续的.
最长公共子序列:子串在原字符串中是最长且可以不连续的.

二.解题步骤
按照上一篇动态规划的解题步骤:
1)找出最长公共子序列的结构
设序列X = {x1,x2,…xm}和Y = {y1,y2,…yn}的最长公共子序列为Z = {z1,z2,…zk},则:

若Xm = Yn,则Zk = Xm = Yn,且Zk-1是Xk-1和Yk-1的最长公共子序列
若Xm != Yn 且Zk != Xm ,则Z是Xm-1和Y的最长公共子序列
若Xm != Yn 且Zk != Yn ,则Z是X和Yn-1的最长公共子序列

2)写出子问题的递归结构
这里写图片描述

3)计算最优值
我们用C[i][j]存储X[i]和Y[j]的最长公共子序列长度,
B[i][j]记录C[i][j]的值是由哪一个子问题解到的,在构造最长公共子序列时由其得到最长公共子串的解.

void LCSLength(int m,int n,char *x,char *y,int c[][MAXLEN],int b[][MAXLEN]){    int i,j;    for(i = 0; i <=m; i++) c[i][0]=0;    for(i = 1; i <=n; i++) c[0][i]=0;    for(i = 1; i <= m; i++){        for(j = 1; j <= n; j++){            //注意x序列和c数组下标相差1            if(x[i-1]==y[j-1]){                c[i][j]=c[i-1][j-1]+1;                b[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;            }        }    }}

4)构造最长公共子串
利用回溯的方法,首先从B[i][j]开始,
当B[i][j]=1时,表示Xi和Yj的最长公共子序列是由Xi-1和Yj-1的最长公共子序列加上Xi所得;
当B[i][j]=2时,表示Xi和Yj的最长公共子序列和Xi-1和Yj的最长公共子序列相同;
当B[i][j]=3时,表示Xi和Yj的最长公共子序列和Xi和Yj-1的最长公共子序列相同;

void LCS(int i, int j, char *x,int b[][MAXLEN]){    if(i==0||j==0)    {return;}    if(b[i][j]==1){        LCS(i-1,j-1,x,b);        //注意x序列和c数组下标相差1        printf("%c ",x[i-1]);    }else if(b[i][j]==2){        LCS(i-1,j,x,b);    }else{        LCS(i,j-1,x,b);    }}

编辑距离问题与此有异曲同工之妙,可以一起做一下.
这里写图片描述

这里写图片描述

0 0
原创粉丝点击