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

    最长公共子序列问题:
       给定两个序列 X = {x1, x2, ......, xm } 和 Y = {y1, y2, ......, yn },找出 X 和 Y 的最长公共子序列。
    一个给定序列的子序列是在该序列中删去若干个元素后得到的序列。给定两个序列 X 和 Y ,当另一序列 Z 既是 X 的子序列又是 Y 的子序列时,称 Z 是序列 X 和 Y 的公共子序列。
    例如,若 X = {A, B, C, B, D, A, B }, Y = {B, D, C, A, B, A },
    序列{B, C, A }是 X 和 Y 的一个公共子序列,序列{B, C, B, A }也是 X 和 Y 的一个公共子序列,且为最长公共子序列。

    最长公共子序列问题具有最优子结构性质。

    设序列 X = {x1, x2, ......, xm } 和 Y = {y1, y2, ......, yn }的最长公共子序列为 Z = {z1, z2, ......, zk}
    则(1) 若 xm = yn ,则 zk = xm = yn ,且 Zk-1 是 Xm-1 和 Yn-1 的最长公共子序列。
    (2) 若 xm != yn 且 zk != xm ,则 Z 是 Xm-1 和 Y 的最长公共子序列。
    (3) 若 xm != yn 且 zk != yn ,则 Z 是 X 和 Yn-1 的最长公共子序列。
    其中:
    Xm-1 = {x1, x2, ......, xm-1 }; Yn-1 = {y1, y2, ......, yn-1}; Zk-1 = {z1, z2, ......, zk-1}。

    引进一个二维数组C,用C[i,j]记录X与Y的LCS的长度,如果我们是自底向上进行递推计算,那么在计算C[i,j]之前,
    C[i-1,j-1], C[i-1,j]与C[i,j-1]均已计算出来。此时我们根据X[i]=Y[j]还是X[i]≠Y[j],就可以计算出C[i,j]:

    若X[i]=Y[j],则执行C[i,j]=C[i-1,j-1]+1;若X[i]≠Y[j],则根据:

    C[i-1,j]≥C[i,j-1],则C[i,j]取C[i-1,j];否则C[i,j]取C[i,j-1]。

    为了构造出LCS,使用一个m×n的二维数组b,b[i,j]记录C[i,j]是通过哪一个子问题的值求得的,以决定搜索的方向:
    若X[i]=Y[j],则b[i,j]中记入“1”;

    若C[i-1,j]≥C[i,j-1],则b[i,j]中记入“0”;

    若C[i-1,j] < C[i,j-1],则b[i,j]中记入“-1”;
    为节省空间,数组b亦可不用,直接根据X[i]=Y[j]还是X[i]≠Y[j]以及C[i,j-1],C[i-1,j]来找出搜索方向.

    
    
    import java.util.Random;
    public class LCS {
        public static void main(String[] args) {
            //设置字符串长度
            int substringLength1 = 100;
            int substringLength2 = 100;
            // 随机生成字符串
            String x = GetRandomStrings(substringLength1);
            String y = GetRandomStrings(substringLength2);
            Long startTime = System.nanoTime();
            // 构造二维数组记录子问题x[i]和y[i]的LCS的长度
            int[][] opt = new int[substringLength1 + 1][substringLength2 + 1];
            // 动态规划计算所有子问题
            for (int i = substringLength1 - 1; i >= 0; i--) {
                for (int j = substringLength2 - 1; j >= 0; j--) {
                    if (x.charAt(i) == y.charAt(j))
                        opt[i][j] = opt[i + 1][j + 1] + 1;
                    else
                        opt[i][j] = Math.max(opt[i + 1][j], opt[i][j + 1]);
                }
            }
            System.out.println("substring1:"+x);
            System.out.println("substring2:"+y);
            System.out.print("LCS:");
            int i = 0, j = 0;
            while (i < substringLength1 && j < substringLength2) {
                if (x.charAt(i) == y.charAt(j)) {
                    System.out.print(x.charAt(i));
                    i++;
                    j++;
                } else if (opt[i + 1][j] >= opt[i][j + 1])
                    i++;
                else
                    j++;
            }
            Long endTime = System.nanoTime();
            System.out.println(" Totle time is " + (endTime - startTime) + " ns");
        }
        //取得定长随机字符串
        public static String GetRandomStrings(int length) {
            StringBuffer buffer = new StringBuffer("abcdefghijklmnopqrstuvwxyz");
            StringBuffer sb = new StringBuffer();
            Random r = new Random();
            int range = buffer.length();
            for (int i = 0; i < length; i++) {
                sb.append(buffer.charAt(r.nextInt(range)));
            }
            return sb.toString();
        }
    }
    


  • 相关阅读:
    OK335x mksd.sh hacking
    Qt jsoncpp 对象拷贝、删除、函数调用 demo
    OK335xS 256M 512M nand flash make ubifs hacking
    Qt QScrollArea and layout in code
    JsonCpp Documentation
    Qt 4.8.5 jsoncpp lib
    Oracle数据库生成UUID
    freemarker得到数组的长度
    FreeMarker中if标签内的判断条件
    freemarker语法
  • 原文地址:https://www.cnblogs.com/duanxingxing/p/6550641.html
Copyright © 2011-2022 走看看