zoukankan      html  css  js  c++  java
  • 最长公共子序列

    这里所求的最长公共子序列,指的是最长公共子序列的长度。

    基本思路和求最长公共子串差不多 只是在一处有差别,代码也比较简单。  

     public static int lcs(String s1, String s2) {
            int len1 = s1.length();
            int len2 = s2.length();
            //flag 表示最长功能子串起始位置
            int flag = -1;
            if (len1 == 0 || len2 == 0) {
                return 0;
            }
            //为了初始化方便 使用了n+1个空间 result[i][j]表示在i,j出最长公共子序列的最长长度(不一定包含s1[i],s2[j])这点和最长公共子串是不一样的
         
            int[][] result = new int[len1 + 1][len2 + 1];
            for (int i = 0; i < len1; i++) {
                result[i][0] = 0;
            }
            for (int i = 0; i < len2; i++) {
                result[0][i] = 0;
            }
            for (int i = 0; i < len1; i++) {
                for (int j = 0; j < len2; j++) {
                    if (s1.charAt(i) == s2.charAt(j)) {
                        result[i + 1][j + 1] = result[i][j] + 1;
                    } else {
                //这一步和求最长公共子串有差别 因为 子序列不要求连续性 所以如果当前两个值不相等 那么就等于下面两个值中的一个
                        result[i + 1][j + 1] = Math.max(result[i + 1][j], result[i][j + 1]);
                    }
                }
            }
            return result[len1][len2];
        }

    本身思路就是普通的动态规划,没有什么特殊情况 ,但是我们发现我们在求解result[i+1][j+1]的时候 只用到了两组值 分别是result[i]和result[j]所以我们不需要创建这么大的二维数组

    只创建一个这样的就可以 交替使用 result[0]和result[1]就可以求出解

     int[][] result = new int[2][len2 + 1];
     public static int Lcs1(String s1, String s2) {
            int len1 = s1.length();
            int len2 = s2.length();
            //flag 表示最长功能子串起始位置
            int flag = -1;
            if (len1 == 0 || len2 == 0) {
                return 0;
            }
            int pre = 0;
            int cur = 1;
            int[][] result = new int[2][len2 + 1];
            for (int i = 0; i < len2; i++) {
                result[0][i] = 0;
            }
            result[1][0] = 0;
            for (int i = 0; i < len1; i++) {
                for (int j = 0; j < len2; j++) {
                    if (s1.charAt(i) == s2.charAt(j)) {
                        result[cur][j + 1] = result[pre][j] + 1;
                    } else {
                        result[cur][j + 1] = Math.max(result[cur][j], result[pre][j + 1]);
                    }
                }
                //每次循环完之后交换cur 和 pre的值循环使用
                int temp = cur;
                cur = pre;
                pre = temp;
            }
            //因为最后一次循环后依然发生了一次交换 所以最大值存在result[pre][len2]中
            return result[pre][len2];
        }

    具体过程如上面代码所示。其实还可以更进一步使用一维数组 ,这里先不实现

  • 相关阅读:
    array_udiff_assoc — 带索引检查计算数组的差集,用回调函数比较数据
    array_sum — 对数组中所有值求和
    array_splice — 去掉数组中的某一部分并用其它值取代
    array_slice — 从数组中取出一段
    array_multisort — 对多个数组或多维数组进行排序
    array_merge — 合并一个或多个数组
    array_keys — 返回数组中部分的或所有的键名
    array_key_exists — 检查数组里是否有指定的键名或索引
    array_intersect_assoc — 带索引检查计算数组的交集
    array_flip — 交换数组中的键和值
  • 原文地址:https://www.cnblogs.com/shaomys/p/11870044.html
Copyright © 2011-2022 走看看