算法学习笔记----最长公共子序列问题

(说明:由于CSDN的博客中不能添加下标等特殊符号,所以部分内容使用截图的形式)

算法学习笔记----最长公共子序列问题_第1张图片

static void print_lcs(int **b, char *x, int i, int j)
{
    int key;

    if (i == 0 || j == 0) {
        return;
    }

    key = b[i-1][j-1];
    switch (key) {
        case 0:
            print_lcs(b, x, i - 1, j - 1);
            printf("%c ", x[i-1]);
            break;

        case 1:
            print_lcs(b, x, i - 1, j);
            break;

        case 2:
            print_lcs(b, x, i, j - 1);
            break;

        default:
            break;
    }
}

static void lcs_length(char *x, int m, char *y, int n)
{
    int b[m][n];
    int *p[m];
    int c[m+1][n+1];
    int i,j;

    for (i = 1; i <= m; ++i) {
        c[i][0] = 0;
    }
    for (j = 0; 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-1][j-1] = 0;
            } else if (c[i-1][j] >= c[i][j-1]) {
                c[i][j] = c[i-1][j];
                b[i-1][j-1] = 1;
            } else {
                c[i][j] = c[i][j-1];
                b[i-1][j-1] = 2;
            }
        }
    }

    for (i = 0; i < m; ++i) {
        p[i] = b[i];
    }

    print_lcs(p, x, m, n);
    printf("\n");
}

lcs_length()函数中前两个循环分别初始化为序列Y长度为0、序列X长度为0的情况。只要有一个序列的长度为0,则最大公共子序列的长度为0.接下来的两个嵌套循环用来计算X序列和Y序列长度不同时,最大公共子序列的长度,并存储计算最大子序列时选择的子问题最优解。
print_lcs()我们这里使用的是递归来实现,还可以使用循环来代替递归,提高效率。不过在使用循环时,要分配额外的空间来存储最大公共子序列,代码实现如下:
static void print_lcs(int **b, char *x, int i, int j, int length)
{
    char lcs[length];
    int k = length - 1;

    do {
        if (i == 0 || j == 0) {
            break;
        }

        switch (b[i-1][j-1]) {
            case 0:
                lcs[k--] = x[i-1];
                i = i - 1;
                j = j - 1;
                break;

            case 1:
                i = i - 1;
                break;

            case 2:
                j = j - 1;
                break;

            default:
                break;
        }
    } while(1);

    for (i = 0; i < length; ++i) {
        printf("%c ", lcs[i]);
    }
}
 参数中的length就是X序列和Y序列最大公共子序列的长度,可以计算完c数组和b数组之后,通过c[m][n]获取。


你可能感兴趣的:(算法学习笔记----最长公共子序列问题)