动态规划之最大公共子序列

题目的大意是已知两个字符串,求两个字符串的最大公共子序列。
假设串X[i]是大串,Y[j]是小串,(i>j)那么在问题的分析中,有这样的假设:
设C[][],来表示最大子串的长度,Z[]表示最大子串,如:C[i][j]表示X[i]与Y[j]的最大子串长度,那么有:
①如果X[i]=Y[j],那么,C[i][j]=C[i-1][j-1]+1,表示X[i-1],Y[j-1]的最大字串长度,Z[i]=X[i]=Y[j]。
②如果X[i]≠Y[j],且X[i]≠Z[i],则可能Y[j]=Z[i]=X[i-n](n>0),由于递推算法的运算,n最小取1,那么最后一个子序数Z[i]是前X[i-1]与前Y[j]的公共子序列,那么,有C[i][j]=C[i-1][j],由于运算是从后往前的递推运算,所以在i--,j--的运算过程中,会对Y[j],X[i-1]进行判断。
③如果X[i]≠Y[j]且Y[j]≠Z[i],则可能X[i]=Z[i]=Y[j-n](n>0),由于递推算法的运算,n最小取1,那么最后一个子序数Z[i]是前Y[j-1]与前X[i]的公共子序列,那么,有C[i][j]=C[i][j-1],由于运算是从后往前的递推运算,所以在i--,j--的运算过程中,会对Y[j-1],X[i]进行判断。
但是存在的一个问题是,我们并不知道Z的具体数目,则可以另加判断。
①当X[i]==Y[j]时可以直接进行运算:C[i][j]=C[i-1][j-1]+1。
②当两者不相等时,判断是否有X[i]与Y或者X与Y[j]构成新的子序列元素,,即判断C[i-1][j]与C[i][j-1]的大小关系。C[i][j]取极大,表示当前的最大子序列元素个数。
最后C[i][j]即为解。
如果想要得到子序列的具体输出情况,为了避免重复输出,可以另加数组Z[i][j]来存放参数,在对C数组赋值时同时也进行赋值。
如果是情况①,那么可以赋值Z[i][j]=1,输出的时候只要是1就输出X[i]或者Y[j],同时传参的项数为i-1,j-1。
如果是情况②,那么可以赋值为2,不进行输出,递归参数即为i-1,j。
如果是情况③,那么可以赋值为3,不进行输出,递归参数即为i,j-1。
具体代码如下:

#include <stdio.h>
#include <string.h>
#define MAXLEN 100

void LCSLength(char *x, char *y, int m, int n, int c[][MAXLEN], int b[][MAXLEN])
{
    int i, j;
    
    for(i = 0; i <= m; i++)
        c[i][0] = 0;
    for(j = 1; j <= n; j++)
        c[0][j] = 0;
    for(i = 1; i<= m; i++)
    {
        for(j = 1; j <= n; j++)
        {
            if(x[i-1] == y[j-1])
            {
                c[i][j] = c[i-1][j-1] + 1;
                b[i][j] = 0;
            }
            else if(c[i-1][j] >= c[i][j-1])
            {
                c[i][j] = c[i-1][j];
                b[i][j] = 1;
            }
            else
            {
                c[i][j] = c[i][j-1];
                b[i][j] = -1;
            }
        }
    }
}

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

int main(int argc, char **argv)
{
    char x[MAXLEN] = {"ABCBDAB"};
    char y[MAXLEN] = {"BDCABA"};
    int b[MAXLEN][MAXLEN];
    int c[MAXLEN][MAXLEN];
    int m, n;
    
    m = strlen(x);
    n = strlen(y);
    
    LCSLength(x, y, m, n, c, b);
    PrintLCS(b, x, m, n);
    
    return 0;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容