华为OJ之最长公共子序列
题目描述:
对于两个给定的字符串,给出他们的最长公共子序列。
题目分析:
1,在之前的博文(http://www.cnblogs.com/yonguo123/p/6711360.html)中我们讨论了最长公共子串的问题,当时也指出最长公共子串其实就是最长公共子序列的一种特殊情况,那么今天我们就来一起研究一下最长公共子序列的求解;
2,最长公共子序列的定义这里不再赘述,和之前的最长公共子串一样,我们这次仍然采用动态规划和回溯的思想来解决;
3,我们假设输入为str1, str2, 首先来通过动态规划获取最大最序列的长度:
3-1,构建一个二维数组tempMatrix,维度为(str1.length + 1), (str2.length + 1);
3-2,temp[i][j]的含义:str1.subString(0, i)和str2.subString(0, j)的最长公共子序列(注意理解这个数组的含义)的长度;
3-3,显然temp[i][j] == 0, 当i == 0 || j == 0;
3-4,否则,当 str1.charAt(i - 1) == str2.charAt(j - 1)时,temp[i][j] = temp[i - 1][j - 1] + 1, 否则temp[i][j] == max{temp[i, j - 1], temp[i - 1, j]}(具体原因大家自己思考一下,可以从新加入的两个尾字符是否会出现在新的LCS中来思考);
4,已经构建好了tempMatix矩阵,实际上tempMatrix[str1.length][str2.length]就是LCS的长度了,而且tempMatrix也保存了必要的回溯信息,下面我们继续构建一个String[][] flagMatrix = new String[str1.length][str2.length], 规则如下:

可能会有同学对这个左上,上,左的取值有疑问,请看下面这张回溯图:

实际上回溯时具体的方向与我们对于坐标的选取是有关系的,所以大家在写代码之前,应该先把坐标方向规定好。之后的工作就是利用flagMatrix来逐步回溯,详细的实现细节见代码。
5,如果还有其它更好的想法,欢迎大家与我交流^-^
具体代码(Java实现):
import java.util.Scanner;
public class LCSequence {
public static void main(String[] args) {
String[] paras = getInput();
System.out.println(getLongestSubsequence(paras[0], paras[1]));
}
public static String[] getInput() {
Scanner reader = new Scanner(System.in);
String[] paras = new String[2];
paras[0] = reader.nextLine();
paras[1] = reader.nextLine();
reader.close();
return paras;
}
public static String[][] getGenerationMatirx(String str1, String str2) {
int[][] temp = new int[str1.length() + 1][str2.length() + 1];
String[][] flag = new String[str1.length() + 1][str2.length() + 1];
for (int i = 0; i <= str1.length(); i ++) {
temp[i][0] = 0;
}
for (int i = 0; i <= str2.length(); i ++) {
temp[0][i] = 0;
}
//迭代获取最长公共子序列的生成矩阵
for (int i = 1; i <= str1.length(); i ++) {
for (int j = 1; j <= str2.length(); j ++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
temp[i][j] = temp[i - 1][j - 1] + 1;
flag[i][j] = "left_up";
} else {
if (temp[i - 1][j] >= temp[i][j - 1]) {
temp[i][j] = temp[i - 1][j];
flag[i][j] = "up";
} else {
temp[i][j] = temp[i][j - 1];
flag[i][j] = "left";
}
}
}
}
return flag;
}
public static String getLongestSubsequence(String str1, String str2) {
String[][] flagMatrix = getGenerationMatirx(str1, str2);
String tempString = "";
for (int i = str1.length(), j = str2.length(); i > 0 && j > 0;) {
if (flagMatrix[i][j].equals("left_up")) {
tempString += str1.charAt(i - 1);
i --;
j --;
} else if (flagMatrix[i][j].equals("left")) {
j --;
} else {
i --;
}
}
return new StringBuffer(tempString).reverse().toString();
}
}
运行结果:

这里需要注意一点,因为LCS可能不止一个,所以对于flagMatrix的赋值其实不止一种情况,代码34行中大于或者大于等于都可以,但是可能会输出不同的结果。
华为OJ之最长公共子序列的更多相关文章
- 华为OJ之最长公共子串
题目描述: 对于两个给定的字符串,给出他们的最长公共子串. 题目分析: 1,最长公共子串(LCS)实际上是最长公共子序列的一种特殊情况,相当于是求连续的最长子序列.我们今天先解决这个特殊情况,后续博文 ...
- CJOJ 2044 【一本通】最长公共子序列(动态规划)
CJOJ 2044 [一本通]最长公共子序列(动态规划) Description 一个给定序列的子序列是在该序列中删去若干元素后得到的序列.确切地说,若给定序列X,则另一序列Z是X的子序列是指存在一个 ...
- 38-最长公共子序列(dp)
最长公共子序列 https://www.nowcoder.com/practice/c996bbb77dd447d681ec6907ccfb488a?tpId=49&&tqId=293 ...
- 用python实现最长公共子序列算法(找到所有最长公共子串)
软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
- [Data Structure] LCSs——最长公共子序列和最长公共子串
1. 什么是 LCSs? 什么是 LCSs? 好多博友看到这几个字母可能比较困惑,因为这是我自己对两个常见问题的统称,它们分别为最长公共子序列问题(Longest-Common-Subsequence ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- LintCode 77: 最长公共子序列
public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...
- 删除部分字符使其变成回文串问题——最长公共子序列(LCS)问题
先要搞明白:最长公共子串和最长公共子序列的区别. 最长公共子串(Longest Common Substirng):连续 最长公共子序列(Longest Common Subsequence,L ...
随机推荐
- 在linux中导入sql文件的方法分享(使用命令行转移mysql数据库)
因导出sql文件 在你原来的网站服务商处利用phpmyadmin导出数据库为sql文件,这个步骤大家都会,不赘述. 上传sql文件 前面说过了,我们没有在云主机上安装ftp,怎么上传呢? 打开ftp客 ...
- css中那些容易被我们程序猿所忽略的选择器
css中那些容易被我们程序猿所忽略的选择器 作为一个程序猿,我们可能会遇到这样的问题,假如:有5个li,要求给第三个li设置背景颜色怎么办?有人会说,用JS啊,循环遍历出第三个不就行了.但是,用JS解 ...
- 使用OTP动态口令(每分钟变一次)进行登录认证
GIT地址:https://github.com/suyin58/otp-demo 在对外网开放的后台管理系统中,使用静态口令进行身份验证可能会存在如下问题: (1) 为了便于记忆,用户多选择有特征作 ...
- 通过JSP+servlet实现文件上传功能
在TCP/IP中,最早出现的文件上传机制是FTP.它将文件由客户端到服务器的标准机制. 但是在JSP中不能使用FTP来上传文件,这是有JSP的运行机制所决定的. 通过为表单元素设置Method=&qu ...
- 12.ThreadPoolExecutor线程池原理及其execute方法
jdk1.7.0_79 对于线程池大部分人可能会用,也知道为什么用.无非就是任务需要异步执行,再者就是线程需要统一管理起来.对于从线程池中获取线程,大部分人可能只知道,我现在需要一个线程来执行一个任 ...
- [1] C# IS & AS讲解
c# 中 is和as 操作符是用来进行强制类型转换的 is : 检查一个对象是否兼容于其他指定的类型,并返回一个Bool值,永远不会抛出异常 object o = new object(); if ( ...
- python 标准库 -- signal
signal 的核心是 : 设置信号处理函数. 预定义信号 signal.SIG_DFL signal.SIGBUS signal.SIGFPE signal.SIGIO signal.SIGPOLL ...
- jQuery未定义错误原因(jQuery is not define)
使用jQuery时,必须把它写在最前面,这样浏览器才会先加载jQuery,否则会提示缺少对象. 正确 <script type="text/javascript" src=& ...
- 这是您一直期待的所有iOS 11功能的屏幕截图
Tips 原文作者:Chris Mills 原文地址:Here's all the iOS 11 screenshots you've been waiting for 除非你已经深陷VR其中,否则现 ...
- java利用反射获取类的属性及类型
java利用反射获取类的属性及类型. import java.lang.reflect.Field; import java.math.BigDecimal; import java.util.Map ...