最长公共子序列问题:算法与代码实现

题目描述

给定两个序列 X = (x1, x2, …, xm) 和 Y = (y1, y2, …, yn),当另一个序列 Z 既是 X 子序列又是 Y 的子序列时,称 Z 是序列 X 和 Y 的公共子序列。根据已知两个序列,求二者公共最长子序列。

输入格式

序列 X 和序列 Y

输出格式

公共最长子序列及长度、求解问题过程中填写的表中数据

输入示例

请输入 X 序列长度: 6 X 序列: abcbdb 请输入 Y 序列长度: 9 Y 序列: acbbabdbb

输出示例

表中数据如下: 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 1 2 2 2 2 2 2 2 0 1 2 2 2 2 2 2 2 2 0 1 2 3 3 3 3 3 3 3 0 1 2 3 3 3 3 4 4 4 0 1 2 3 4 4 4 4 5 5 最长公共子序列长度:5 最长公共子序列: acbdb

算法思路

1、建立两个二维数组 L 和 S,L 数组记录公共子序列的长度,S 数组记录 L 数组的状态。 2、状态转移方程: 1)、当 x[i] == y[j] 时,L[i][j] = L[i-1][j-1] + 1,S[i][j] = 1。 2)、当 x[i] != y[j] 时,L[i][j] = max(L[i-1][j], L[i][j-1]),S[i][j] = 2 或 3。 3、从 S 数组中反推出公共子序列。

C++ 代码

#include <stdio.h>

int CommonOrder(char x[], int m, char y[], int n, char z[])
{
    int i, j, k, L[m + 1][n + 1], S[m + 1][n + 1];
    for (j = 0; j <= n; j++)
        L[0][j] = 0;
    for (i = 0; i <= m; i++)
        L[i][0] = 0;
    for (i = 1; i <= m; i++)
        for (j = 1; j <= n; j++)
            if (x[i] == y[j])
            {
                L[i][j] = L[i - 1][j - 1] + 1;
                S[i][j] = 1;
            }
            else if (L[i][j - 1] >= L[i - 1][j])
            {
                L[i][j] = L[i][j - 1];
                S[i][j] = 2;
            }
            else {
                L[i][j] = L[i - 1][j];
                S[i][j] = 3;
            }
    i = m;
    j = n;
    k = L[m][n];
    while (i > 0 && j > 0)
    {
        if (S[i][j] == 1) {
            z[--k] = x[i];
            --i;
            --j;
        }
        else if (S[i][j] == 2)
            --j;
        else
            --i;
    }
    return L[m][n];
}

int main()
{
    int m, n, L[m + 1][n + 1];
    printf("请输入 X 序列长度:");
    scanf("%d", &m);
    char x[m + 1];
    printf("X 序列:");
    scanf("%s", x);
    printf("请输入 Y 序列长度:");
    scanf("%d", &n);
    char y[n + 1];
    printf("Y 序列:");
    scanf("%s", y);
    char z[m + n + 1];
    int len = CommonOrder(x, m, y, n, z);
    printf("表中数据如下:
");
    for (int i = 0; i <= m; i++)
    {
        for (int j = 0; j <= n; j++)
            printf("%d  ", L[i][j]);
        printf("\n");
    }
    printf("最长公共子序列长度:%d\n", len);
    printf("最长公共子序列:");
    for (int i = 0; i < len; i++)
        printf("%c ", z[i]);
    return 0;
}

总结

本文介绍了最长公共子序列问题的定义、算法思路和 C++ 代码实现。通过动态规划方法,使用两个二维数组记录子序列长度和状态,并最终反推出最长公共子序列。该算法简单易懂,代码实现较为简洁,适用于解决不同序列的最长公共子序列问题。

最长公共子序列问题:算法与代码实现

原文地址: https://www.cveoy.top/t/topic/n74B 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录