zoukankan      html  css  js  c++  java
  • 算法:Common Subsequence(动态规划 Java 最长子序列)

    Description

    A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = < x1, x2, ..., xm > another sequence Z = < z1, z2, ..., zk > is a subsequence of X if there exists a strictly increasing sequence < i1, i2, ..., ik > of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = < a, b, f, c > is a subsequence of X = < a, b, c, f, b, c > with index sequence < 1, 2, 4, 6 >. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y.

    Input

    The program input is from the std input. Each data set in the input contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct.

    Output

    For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line.

    Sample Input

    abcfbc         abfcab
    programming    contest 
    abcd           mnp
    

    Sample Output

    4
    2
    0
    

    Common Subsequence

    求最大子序列的问题:

    递推关系:c[][]存储最长子序列长度

    $$ c[i][j] = egin{cases} 0 & i = 0, j = 0 \ c[i - 1][j - 1] + 1 & i > 0, j > 0; str\_x[i] = str\_y[j] \ max ( c[i][j - 1], c[i - 1][j] ) & i > 0, j > 0; str\_x[i] e str\_y[j] end{cases} $$

    AC代码:

    import java.util.Scanner;
    
    public class Main {
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            String str1, str2;
            while (sc.hasNext()){
                str1 = sc.next();
                str2 = sc.next();
                System.out.println(LcsLength(str1.toCharArray(), str2.toCharArray()));
            }
            sc.close();
        }
    
        public static int LcsLength(char a[], char b[]){
            int aL = a.length;
            int bL = b.length;
            int ans[][] = new int[aL + 1][bL + 1];
            for (int i = 0; i <= aL; i++) {
                ans[i][0] = 0;
            }
            for (int i = 0; i <= bL; i++) {
                ans[0][i] = 0;
            }
            for (int i = 1; i <= aL; i++) {
                for (int j = 1; j <= bL; j++) {
                    if (a[i - 1] == b[j - 1])
                        ans[i][j] = ans[i - 1][j - 1] + 1;
                    else if (ans[i][j - 1] >= ans[i - 1][j])
                        ans[i][j] = ans[i][j - 1];
                    else
                        ans[i][j] = ans[i - 1][j];
                }
            }
            return ans[aL][bL];
        }
    }
    

    可以输出最长子序列之一的代码:

    import java.util.Scanner;
    
    public class Main {
    
        public static int x[][];
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            String str1, str2;
            while (sc.hasNext()) {
                str1 = sc.next();
                str2 = sc.next();
                System.out.println("最大子序列长度: " + LcsLength(str1.toCharArray(), str2.toCharArray()));
            }
            sc.close();
        }
    
        public static int LcsLength(char a[], char b[]) {
            int aL = a.length;      // a数组的长度
            int bL = b.length;      // b数组的长度
            int ans[][] = new int[aL + 1][bL + 1];  // 存储i,j当前的最长子序列长度
            x = new int[aL + 1][bL + 1];            // 存储ans[i][j]是斜对角还是左边,上边来的
            for (int i = 0; i <= aL; i++) {
                ans[i][0] = 0;          // 空的子序列都为0
            }
            for (int i = 0; i <= bL; i++) {
                ans[0][i] = 0;          // 空的子序列都为0
            }
            for (int i = 1; i <= aL; i++) {
                for (int j = 1; j <= bL; j++) {
                    if (a[i - 1] == b[j - 1]) {  // 判断字符是否相等
                        ans[i][j] = ans[i - 1][j - 1] + 1;  // 相等长度加1
                        x[i][j] = 1;            // 标记为相等斜着来的
                    } else if (ans[i][j - 1] >= ans[i - 1][j]) { // 左边大于上边就用最大的
                        ans[i][j] = ans[i][j - 1];
                        x[i][j] = 2;            // 标记为左边来的
                    } else {
                        ans[i][j] = ans[i - 1][j];
                        x[i][j] = 3;            // 标记为上边来的
                    }
                }
            }
            System.out.print("最大子序列: ");
            Lcs(aL, bL, a);
            System.out.print('
    ');
    
            return ans[aL][bL];
        }
    // 递归输出最大子序列其中一个
        public static void Lcs(int i, int j, char a[]) {
            if (i == 0 || j == 0)
                return;
            if (x[i][j] == 1) {
                Lcs(i - 1, j - 1, a);
                System.out.print(a[i - 1]);
            } else if (x[i][j] == 2)
                Lcs(i, j - 1, a);
            else if (x[i][j] == 3)
                Lcs(i - 1, j, a);
        }
    }
    
  • 相关阅读:
    第三节:模板模式——在Spring框架应用
    第二节:模板模式——模板模式应用
    idea ---- intelij IDEA安装
    计算机基础 ---- 编码(er)
    preg_match一些问题
    php 两个值进行比较的问题
    php中in_array一些问题
    配置完php.ini中的扩展库后,重启apache出现错误1067
    基于Intel 174;E810 的OVS-DPDK VXLAN TUNNEL性能优化
    tc filter 工作模式:传统模式和 direct-action 模式
  • 原文地址:https://www.cnblogs.com/yanhua-tj/p/13996567.html
Copyright © 2011-2022 走看看