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

     

    最长公共子序列:可以不连续

    最长公共子串:必须连续

    求最长公共子序列:

    引进一个二维数组c[][],用c[i][j]记录X[i]与Y[j] 的LCS 的长度,b[i][j]记录c[i][j]是通过哪一个子问题的值求得的,以决定搜索的方向。
    我们是自底向上进行递推计算,那么在计算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]。

    问题的递归式写成:


     

    recursive formula

    回溯输出最长公共子序列过程:

    flow

     

    算法分析:
    由于每次调用至少向上或向左(或向上向左同时)移动一步,故最多调用(m * n)次就会遇到i = 0或j = 0的情况,此时开始返回。返回时与递归调用时方向相反,步数相同,故算法时间复杂度为Θ(m * n)。

     

    package kpp.base;
    /**
     * 获取两个字符串的最长公共子序列
     * @author kpp
     *
     */
    public class LCSTest {
        private static String lcs = "";
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            //保留空字符串是为了getLength()方法的完整性也可以不保留
            //但是在getLength()方法里面必须额外的初始化c[][]第一个行第一列
            String firstStr = "ABCBDAB";
            String secondStr = "BDCABA";
            
            
            /*String[] x = new String[firstStr.length()+1];
            String[] y = new String[secondStr.length()+1];*/
            
            String[] x = strToArray(firstStr);
            String[] y = strToArray(secondStr);
            /*String[] x = {"", "A", "B", "C", "B", "D", "A", "B"};  
            String[] y = {"", "B", "D", "C", "A", "B", "A"}; */ 
            
            int[][] b = getSearchRoad(x, y);
            
            Display(b, x, x.length-1, y.length-1);
            
            System.out.println("lcs:"+lcs);
        }
        
        /**
         * 字符串转数组,并且数组的第0个元素为""
         * @param str
         * @return
         */
        private static String[] strToArray(String str){
            
            String[] strArray = new String[str.length()+1];
            
            strArray[0] = "";
                    
            for(int i = 1; i < strArray.length;i++){
                strArray[i] = ""+str.charAt(i-1);
            }
            return strArray;
        }
        
        
        /**
         * 获得LCS矩阵的路径走向
         * @param x 第一个数组
         * @param y 第二个数组
         * @return 返回一个记录决定搜索的方向的数组
         */
        public static int[][] getSearchRoad(String[] x, String[] y)
        {
            int[][] b = new int[x.length][y.length];
            int[][] c = new int[x.length][y.length];
            
            for(int j = 0;j < y.length;j++){
                c[0][j] = 0;
            }
            for(int i = 0;i < x.length;i++){
                c[i][0] = 0;
            }
            
            for(int i=1; i<x.length; i++)
            {
                for(int j=1; j<y.length; j++)
                {
                    //对应第一个性质
                    //x[i].equals(y[j])是指x[i]与y[j]的值相同
                    if( x[i].equals(y[j]))
                    {
                        c[i][j] = c[i-1][j-1] + 1;
                        b[i][j] = 1;
                    }
                    //x[i] == y[j]是指x[i]与y[j]的地址相同
                    /*if( x[i] == y[j])
                    {
                        c[i][j] = c[i-1][j-1] + 1;
                        b[i][j] = 1;
                    }*/
                    //对应第二或者第三个性质
                    else if(c[i-1][j] >= c[i][j-1])
                    {
                        c[i][j] = c[i-1][j];
                        b[i][j] = 0;
                    }
                    //对应第二或者第三个性质
                    else
                    {
                        c[i][j] = c[i][j-1];
                        b[i][j] = -1;
                    }
                }
            }    
            
            return b;
        }
        /**
         * 自矩阵右下至左上回溯,根据搜索路径获取LCS
         * @param b 搜索路径数组
         * @param x 第一个数组
         * @param i 
         * @param j 
         */
        public static void Display(int[][] b, String[] x, int i, int j)
        {
            
            if(i == 0 || j == 0)
                return ;
            
            if(b[i][j] == 1)
            {
                Display(b, x, i-1, j-1);
                lcs += x[i];
            }
            else if(b[i][j] == 0)
            {
                Display(b, x, i-1, j);
            }
            else if(b[i][j] == -1)
            {
                Display(b, x, i, j-1);
            }
        }
    
    }
  • 相关阅读:
    Ubuntu 14.04/16.04/18.04安装最新版Eigen3.3.5
    Ubuntu16.04系统安装谷歌浏览器(Google chorm)
    Anaconda3(6)安装opencv
    Ubuntu 16.04 几个国内更新源
    Anaconda3(4-1)ubuntu1604安装pytorch
    Anaconda3(5-3)ubuntu1604安装pycharm
    无人机姿态定位
    Ubuntu16.04--安装Anaconda
    Airsim(1)安装配置win10-vs2015-cuda10-opencv394+扩展版版本+cmake
    cuda加速拼接
  • 原文地址:https://www.cnblogs.com/kangpp/p/4384297.html
Copyright © 2011-2022 走看看