当前位置: 首页 > news >正文

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);
        }
    }

}

 

转载于:https://www.cnblogs.com/kangpp/p/4384297.html

相关文章:

  • 正则表达式的概述
  • 防止APK反编译和二次加密
  • where 1=-1 and 1=1 会不会影响查询效率?
  • 你正在用却不知道它们让微信比其它社交App更强大的6大功能
  • 毕业后两个月的日子--奋斗的菜鸟
  • 关于C++类型检查的一点小挫折
  • MySQL基础(一)
  • rest api方式实现对文档库的管理
  • 程序员的苦与乐
  • 【算法学习笔记】27.动态规划 解题报告 SJTU OJ 1254 传手绢
  • Android 通过代码设置radiobutton不同方位图标的两种方法
  • 【嵌入式开发板】大家都在玩儿的4412开发板
  • Hadoop2源码分析-MapReduce篇
  • CentOS 7安装后配置笔记
  • Linux常用的基本命令11
  • 【跃迁之路】【444天】程序员高效学习方法论探索系列(实验阶段201-2018.04.25)...
  • Fastjson的基本使用方法大全
  • happypack两次报错的问题
  • HashMap剖析之内部结构
  • If…else
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • Java 最常见的 200+ 面试题:面试必备
  • JavaScript设计模式与开发实践系列之策略模式
  • Netty源码解析1-Buffer
  • 工程优化暨babel升级小记
  • 讲清楚之javascript作用域
  • 深度学习中的信息论知识详解
  • 我的面试准备过程--容器(更新中)
  • 我感觉这是史上最牛的防sql注入方法类
  • 一、python与pycharm的安装
  • 栈实现走出迷宫(C++)
  • k8s使用glusterfs实现动态持久化存储
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​插件化DPI在商用WIFI中的价值
  • #if #elif #endif
  • #NOIP 2014# day.2 T2 寻找道路
  • $refs 、$nextTic、动态组件、name的使用
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (附源码)springboot电竞专题网站 毕业设计 641314
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (一)kafka实战——kafka源码编译启动
  • (原创)Stanford Machine Learning (by Andrew NG) --- (week 9) Anomaly DetectionRecommender Systems...
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)EXC_BREAKPOINT僵尸错误
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .mysql secret在哪_MYSQL基本操作(上)
  • .net Application的目录
  • .net core webapi Startup 注入ConfigurePrimaryHttpMessageHandler
  • .net core 连接数据库,通过数据库生成Modell
  • .net mvc部分视图
  • .net 发送邮件
  • .net 后台导出excel ,word
  • .NET设计模式(2):单件模式(Singleton Pattern)