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);
        }
    }
    
  • 相关阅读:
    zabbix实现原理及架构详解
    用Python玩转微信(一)
    你真的用好了Python的random模块吗?
    Authentication of Django
    Django admin 权威指南(一)
    常用查找数据结构及算法(Python实现)
    基于python的七种经典排序算法
    Django 1.10 中文文档------3.2.2 查询操作making queries
    “全能”选手—Django 1.10文档中文版Part4
    Django 1.10 中文文档------3.2.1 模型Models
  • 原文地址:https://www.cnblogs.com/yanhua-tj/p/13996567.html
Copyright © 2011-2022 走看看