• 最长公共子序列(LCS)


    对于最长公共子序列(LCS),是典型的动态规划问题,对于这个问题,可以用如下思路来解答。
    如:X{x1, x2, x3, ... },Y{y1, y2, y3, ...};
    1.当x1 = y1时,则此时已找到一个相同的值,故接下来只需求{x2, x3, x4, ...}和{y2, y3, y4, ...}的LCS。
    2.当x1 != y1时,则此时X和Y的LCS是下面两个LCS的最大值:
      {x2, x3, x4, ...}和{y1, y2, y3, y4, ...}的LCS,
      或者{x1, x2, x3, x4, ...}和{y2, y3, y4, ...}的LCS。
    由上面可以看出这是一个递归问题。
                _
                |     0       i==0或j==0
                |
    c[i][j] = |-    c[i-1][j-1] + 1    如果i,j>0和xi==yj
                |
                |_  max{c[i][j-1], c[i-1][j]} 如果i,j>0和xi != yj
    其实通过代码中的嵌套for循环,即可知道每次通过比较来累积计算长度的。
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    char* LCS(const char* x, const char* y);
    
    int main()
    {
        char* x = "cbfgade";
        char* y = "bcagfde";
    
        char* s = LCS(x, y);
        cout<<"最长公共子序列为:"<<s<<endl;
        cout<<"长度为:"<<strlen(s)<<endl;
        return 0;
    }
    
    char* LCS(const char* x, const char* y)
    {
        int m = strlen(x);
        int n = strlen(y);
    
        int** c = new int*[m + 1];
        for (int i = 0; i < m + 1; i++) {
            c[i] = new int[n + 1];
            //每一行第一个元素初始化为0
            c[i][0] = 0;
        }
    
        //第一行初始化为0
        for (int i = 0; i < n + 1; i++)
            c[0][i] = 0;
    
        for (int i = 1; i < m + 1; i++) {
            for (int j = 1; j < n + 1; j++) {
                if (x[i - 1] == y[j - 1])
                    c[i][j] = c[i - 1][j - 1] + 1;
                else if (c[i][j - 1] >= c[i - 1][j])
                    c[i][j] = c[i][j - 1];
                else
                    c[i][j] = c[i - 1][j];
            }
        }
    
        //c[m][n]值为最短子序列的长度
        //用result来保存逆序LCS,通过c[m][n]的值与c[m - 1][ n - 1],c[m][n - 1],c[m - 1][n]来判断
        int len = c[m][n];
        char* result = new char[len + 1];
        int count = len;
        while (m > 0 && n > 0) {
            if (c[m][n] == c[m - 1][ n - 1] + 1 && x[m - 1] == y[n - 1]) {
                result[--count] = x[m - 1];
                m--;
                n--;
            } else if (c[m][n] == c[m][n - 1]) {
                n--;
            } else {
                m--;
            }
        }
        result[len] = '\0';
    
        //释放内存
        for (int i = 0; i < m + 1; i++)
            delete[] c[i];
        delete []c;
    
        return result;
    }
  • 相关阅读:
    Java反射----------------判断对象是否为空
    docker安装MongoDB创建用户,并用工具Robo连接简单CRUD
    Ubuntu 配置ip地址
    java时间的处理
    oracle my2_ep解密
    oracle 查询前7天的数据
    多表修改和多表删除
    迭代器遍历Map、List、Set
    冒泡排序
    Java有那两类异常?
  • 原文地址:https://www.cnblogs.com/null00/p/2065040.html
Copyright © 2020-2023  润新知