问题描述:

问题】 求两字符序列的最长公共字符子序列

注意:

并不要求子串(字符串一)的字符必须连续出现在字符串二中。

思路分析:

最优子结构和重叠子问题的性质都具有,所以要采取动态规划的算法

最长公共子序列的结构

设序列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。

子问题的递归结构

由最长公共子序列问题的最优子结构性质可知,要找出X=x1, x2, …, xm和Y=y1, y2, …, yn的最长公共子序列,可按以下方式递归地进行:当xm=yn时,找出Xm-1和Yn-1的最长公共子序列,然后在其尾部加上xm(=yn)即可得X和Y的一个最长公共子序列。当xm≠yn时,必须解两个子问题,即找出Xm-1和Y的一个最长公共子序列及X和Yn-1的一个最长公共子序列。这两个公共子序列中较长者即为X和Y的一个最长公共子序列。

由此递归结构容易看到最长公共子序列问题具有子问题重叠性质。

例如,在计算X和Y的最长公共子序列时,可能要计算出X和Yn-1及Xm-1和Y的最长公共子序列。而这两个子问题都包含一个公共子问题,即计算Xm-1和Yn-1的最长公共子序列。

与矩阵连乘积最优计算次序问题类似,我们来建立子问题的最优值的递归关系。用c[i,j]记录序列Xi和Yj的最长公共子序列的长度。其中Xi=x1, x2, …, xi,Yj=y1, y2, …, yj。

当i=0或j=0时,空序列是Xi和Yj的最长公共子序列,故c[i,j]=0。其他情况下,由定理可建立递归关系如下:

代码:

public class ComSubstr {  

    public static void main(String[] arg) {
        String a = "blog.csdn.net";
        String b = "csdn.blogt";
        comSubstring(a, b);
    }  

    private static void comSubstring(String str1, String str2) {
        char[] a = str1.toCharArray();
        char[] b = str2.toCharArray();
        int a_length = a.length;
        int b_length = b.length;
        int[][] lcs = new int[a_length + 1][b_length + 1];
        // 初始化数组
        for (int i = 0; i <= b_length; i++) {
            for (int j = 0; j <= a_length; j++) {
                lcs[j][i] = 0;
            }
        }
        for (int i = 1; i <= a_length; i++) {
            for (int j = 1; j <= b_length; j++) {
                if (a[i - 1] == b[j - 1]) {
                    lcs[i][j] = lcs[i - 1][j - 1] + 1;
                }
                if (a[i - 1] != b[j - 1]) {
                    lcs[i][j] = lcs[i][j - 1] > lcs[i - 1][j] ? lcs[i][j - 1]
                            : lcs[i - 1][j];
                }
            }
        }
        // 输出数组结果进行观察
        for (int i = 0; i <= a_length; i++) {
            for (int j = 0; j <= b_length; j++) {
                System.out.print(lcs[i][j]+",");
            }
            System.out.println("");
        }
        // 由数组构造最小公共字符串
        int max_length = lcs[a_length][b_length];
        char[] comStr = new char[max_length];
        int i =a_length, j =b_length;
        while(max_length>0){
            if(lcs[i][j]!=lcs[i-1][j-1]){
                if(lcs[i-1][j]==lcs[i][j-1]){//两字符相等,为公共字符
                    comStr[max_length-1]=a[i-1];
                    max_length--;
                    i--;j--;
                }else{//取两者中较长者作为A和B的最长公共子序列
                    if(lcs[i-1][j]>lcs[i][j-1]){
                        i--;
                    }else{
                        j--;
                    }
                }
            }else{
                i--;j--;
            }
        }
        System.out.print("最长公共字符串是:");
        System.out.print(comStr);
    }
}

输出结果:

0,0,0,0,0,0,1,2,2,2,2,
0,0,0,0,0,0,1,2,3,3,3,
0,0,0,0,0,0,1,2,3,4,4,
0,0,0,0,0,1,1,2,3,4,4,
0,1,1,1,1,1,1,2,3,4,4,
0,1,2,2,2,2,2,2,3,4,4,
0,1,2,3,3,3,3,3,3,4,4,
0,1,2,3,4,4,4,4,4,4,4,
0,1,2,3,4,5,5,5,5,5,5,
0,1,2,3,4,5,5,5,5,5,5,
0,1,2,3,4,5,5,5,5,5,5,
0,1,2,3,4,5,5,5,5,5,6,
最长公共字符串是:csdn.t  

## 我的微信二维码如下,欢迎交流讨论 ##

欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧,都是干货!

微信订阅号二维码如下:

参考:

http://blog.csdn.net/v_JULY_v/article/details/6110269

http://www.programgo.com/article/74411986718/

LCS问题(最长公共子序列)-动态规划实现的更多相关文章

  1. C++求解汉字字符串的最长公共子序列 动态规划

        近期,我在网上看了一些动态规划求字符串最长公共子序列的代码.可是无一例外都是处理英文字符串,当处理汉字字符串时.常常会出现乱码或者不对的情况. 我对代码进行了改动.使用wchar_t类型存储字 ...

  2. nyoj 36-最长公共子序列 (动态规划,DP, LCS)

    36-最长公共子序列 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:18 submit:38 题目描述: 咱们就不拐弯抹角了,如题,需要你做的就是写 ...

  3. 基于DP的LCS(最长公共子序列)问题

    最长公共子序列,即给出两个序列,给出最长的公共序列,例如: 序列1 understand 序列2 underground 最长公共序列undernd,长度为7 一般这类问题很适合使用动态规划,其动态规 ...

  4. LCS(最长公共子序列)动规算法正确性证明

    今天在看代码源文件求diff的原理的时候看到了LCS算法.这个算法应该不陌生,动规的经典算法.具体算法做啥了我就不说了,不知道的可以直接看<算法导论>动态规划那一章.既然看到了就想回忆下, ...

  5. 【ACM】最长公共子序列 - 动态规划

    最长公共子序列 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 咱们就不拐弯抹角了,如题,需要你做的就是写一个程序,得出最长公共子序列.tip:最长公共子序列也称作最 ...

  6. HDU 1159 Common Subsequence:LCS(最长公共子序列)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1159 题意: 求最长公共子序列. 题解: (LCS模板题) 表示状态: dp[i][j] = max ...

  7. POJ 1458 Common Subsequence (DP+LCS,最长公共子序列)

    题意:给定两个字符串,让你找出它们之间最长公共子序列(LCS)的长度. 析:很明显是个DP,就是LCS,一点都没变.设两个序列分别为,A1,A2,...和B1,B2..,d(i, j)表示两个字符串L ...

  8. NYOJ 36 LCS(最长公共子序列)

    题目链接: http://acm.nyist.edu.cn/JudgeOnline/problem.php?pid=36 最长公共子序列 时间限制:3000 ms  |  内存限制:65535 KB ...

  9. LCS(最长公共子序列)问题

    例题见挑战程序设计竞赛P56 解释:子序列是从原序列中按顺序(可以跳着)抽取出来的,序列是不连续的,这是其和子串最大的区别: 我们可以定义dp数组为dp[i][j],表示的是s1-si和t1-ti对应 ...

  10. LCS(最长公共子序列)

    这个问题很有意思,在生物应用中,经常需要比较两个(或多个)不同生物体的DNA片段.例如,某种生物的DNA可能为S1 = ACCGGTCGAGTGCGCGGAAGCCGGCCGAA,S2 = GTCGT ...

随机推荐

  1. MySQL系列教程(二)

    mySQL执行计划 语法  explain <sql语句> 例如: explain select * from t3 where id=3952602; explain输出解释 +---- ...

  2. Android Multimedia框架总结(二十五)MediaProjection实现手机截屏(无须root)

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/53966818 前言:一年半多以前 ...

  3. Programming In Scala笔记-第九章、控制抽象

    本章主要讲解在Scala中如何使用函数值来自定义新的控制结构,并且介绍Curring和By-name参数的概念. 一.减少重复代码 1.重复代码的场景描述 前面定义的函数,将实现某功能的代码封装到一起 ...

  4. ICL Auto Vectorization

    简介 此文简单介绍如何使用intel c++编译器实现向量化加速. 全文如下安排: base : 待优化的源代码. vectorization : 第一个向量化版本. aligned : 内存对其对向 ...

  5. Swift3中方法可变参数语法的一些改变

    我们知道在Swift2中,默认情况下方法的参数是let值,也就是不可改变的. 不过我们可以在参数前添加var关键字改变其不变性: func foo(var i:Int){ i += 1 print(i ...

  6. 24 服务AIDL

    AIDL远程访问服务的方法 创建一个接口类写上方法 然后修改后缀java为aidl 在服务中创建一个类继承Stub类 在远程访问服务的进程把AIDL文件复制(包名不能改变) XXXX.Stub.asI ...

  7. ProgressBar的简单使用

    当我们的应用在进行耗时操作时,显示一个进度条呈现给用户,让用户知道当前进度是一个很好的体验,接下来我们就来简单了解下ProgressBar(本文主要针对初学者,大神可以绕开啦),先看效果图: 进度条P ...

  8. Django完整的开发一个博客系统

    今天花了一些时间搭了一个博客系统,虽然并没有相关于界面的美化,但是发布是没问题的. 开发环境 操作系统:windows 7 64位 Django: 1.96 Python:2.7.11 IDE: Py ...

  9. TCP连接建立系列 — 客户端的端口选取和重用

    主要内容:connect()时的端口选取和端口重用. 内核版本:3.15.2 我的博客:http://blog.csdn.net/zhangskd 端口选取 connect()时本地端口是如何选取的呢 ...

  10. javascript命名规则

    javascript对大小写敏感(关键字.函数名.变量名等),标识符的首字符必须是字母.下划线或者$符,其后的字符可以含数字 如果之声明了变量,并未对其赋值,默认为undefined javascri ...