算法起步之动态规划LCS
原文:算法起步之动态规划LCS
前一篇文章我们了解了什么是动态规划问题,这里我们再来看动态规划另一个经典问题,最长公共子序列问题(LCS),什么是子序列,我们定义:一个给定序列将其中的0个或者多个元素去掉之后得到的序列就是他的子序列。例如序列x包含(a,b,c,b,d,a,b)那么序列y(b,c,d,b)就是x的一个子序列。公共子序列则是两个序列的公共的子序列,而最长公共子序列则是从两个序列的公共子序列中挑选出长度最长的子序列。
我们用我们说的动态规划的四步来分析这个问题。一刻画最长公共子序列的特征。假设序列X(包含X1,X2……Xm)而序列Y(Y1……Yn)而他们的最长公共子序列为Z(Z1……Zk);那么1如果Xm=Yn则Zk-1是Xm-1与Yn-1的最大公共子序列。2如果Xm!=Yn且Zk!=Xm那么Zk是Xm-1与Yn的最大公共子序列。3如果Xm!=Yn且Zk!=Yn那么Zk是Xm与Yn-1的最大公共子序列。通过这3种情况我们就可以将我们刚才的问题刻画成一个递归的问题。
我们可以通过递归的方式来求出最长公共子序列的长度。然后我们采用自底向上的方法来求出最优解。
public void lcsLength(String x,String y){
int xl=x.length();
int yl=y.length();
int[][] map=new int[xl+1][yl+1];
for (int i = 1; i <=xl; i++) {
for (int j = 1; j <=yl; j++) {
if (x.charAt(i-1)==y.charAt(j-1)) {
map[i][j]=map[i-1][j-1]+1;
}else {
if(map[i-1][j]>map[i][j-1]){
map[i][j]=map[i-1][j];
}else {
map[i][j]=map[i][j-1];
}
}
}
}
System.out.println(map[xl][yl]);
}
public static void main(String[] args) {
new LCS().lcsLength("abcab", "bcadd");
}
这样我们就求得了最长公共子序列的长度,然后我们可以根据改进算法把最长公共子序列打印出来。当然这里改进的方法有太多了,每个人可能都有自己的想法,我只提供一种方法供大家参考(并没有考虑运行效率等因素):
public class LCS {
private StringBuffer sb=new StringBuffer();
private int ox=0;
private int oy=0;
public void lcsLength(String x,String y){
int xl=x.length();
int yl=y.length();
int[][] map=new int[xl+1][yl+1];
for (int i = 1; i <=xl; i++) {
for (int j = 1; j <=yl; j++) {
if (x.charAt(i-1)==y.charAt(j-1)) {
map[i][j]=map[i-1][j-1]+1;
if (i>ox&&j>oy) {
if(map[i][j]>sb.length()){
sb.append(x.charAt(i-1));
ox=i;oy=j;
}
}else {
if (i>ox&&j<oy&&map[i][j]==sb.length()) {
sb.deleteCharAt(sb.length()-1);
sb.append(x.charAt(i-1));
ox=i;oy=j;
}
}
}else {
if(map[i-1][j]>map[i][j-1]){
map[i][j]=map[i-1][j];
}else {
map[i][j]=map[i][j-1];
}
}
}
}
System.out.println(map[xl][yl]);
System.out.println(sb.toString());
}
public static void main(String[] args) {
new LCS().lcsLength("abcab", "bcadd");
}
}
友情提示:转载请注明出处【作者:idlear 博客:http://blog.csdn.net/idlear】
算法起步之动态规划LCS的更多相关文章
- 算法起步之Bellman-Ford算法
原文:算法起步之Bellman-Ford算法 从这篇开始我们开始介绍单源最短路径算法,他是图算法之一,我们前面说的贪心,图的遍历,动态规划都是他的基础,单源最短路径其实说的就是图中节点到节点的最短路径 ...
- 算法起步之A星算法
原文:算法起步之A星算法 用途: 寻找最短路径,优于bfs跟dfs 描述: 基本描述是,在深度优先搜索的基础上,增加了一个启发式算法,在选择节点的过程中,不是盲目选择,而是有目的的选的,F=G+H,f ...
- 算法起步之Kruskal算法
原文:算法起步之Kruskal算法 说完并查集我们接着再来看这个算法,趁热打铁嘛.什么是最小生成树呢,很形象的一个形容就是铺自来水管道,一个村庄有很多的农舍,其实这个村庄我们可以看成一个图,而农舍就是 ...
- 算法起步之Prim算法
原文:算法起步之Prim算法 prim算法是另一种最小生成树算法.他的安全边选择策略跟kruskal略微不同,这点我们可以通过一张图先来了解一下. prim算法的安全边是从与当前生成树相连接的边中选择 ...
- 算法起步之Dijkstra算法
原文:算法起步之Dijkstra算法 友情提示:转载请注明出处[作者 idlear 博客:http://blog.csdn.net/idlear/article/details/19687579 ...
- 算法 递归 迭代 动态规划 斐波那契数列 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 五大常见算法策略之——动态规划策略(Dynamic Programming)
Dynamic Programming Dynamic Programming是五大常用算法策略之一,简称DP,译作中文是"动态规划",可就是这个听起来高大上的翻译坑苦了无数人 ...
- 算法复习周------“动态规划之‘最长公共子序列’”&&《计蒜课》---最长公共子串题解
问题描述: 这个问题其实很容易理解.就是给你两个序列X={x1,x2,x3......xm} Y={y1,y2,y3......ym},要求找出X和Y的一个最长的公共子序列. 例:Xi={A, B, ...
- 关于贪心算法的经典问题(算法效率 or 动态规划)
如题,贪心算法隶属于提高算法效率的方法,也常与动态规划的思路相挂钩或一同出现.下面介绍几个经典贪心问题.(参考自刘汝佳著<算法竞赛入门经典>).P.S.下文皆是我一个字一个字敲出来的,绝对 ...
随机推荐
- Java获取随机数的几种方法
Java获取随机数的几种方法 .使用org.apache.commons.lang.RandomStringUtils.randomAlphanumeric()取数字字母随机10位; //取得一个3位 ...
- 基于visual Studio2013解决面试题之1002公共子串
题目
- 基于visual Studio2013解决面试题之1001去除数字
题目
- 在VC++中使用Tab Control控件
系统环境:Windows 7软件环境:Visual Studio 2008 SP1本次目的:在模态或非模态对话框中使用Tab Control控件,及引申在单/多文档中使用 查阅MSDN文档,对于创建T ...
- Recipes — Bottle 0.13-dev documentation
Recipes - Bottle 0.13-dev documentation Recipes¶ This is a collection of code snippets and examples ...
- MySQL存储引擎:InnoDB和MyISAM的差别/优劣评价/评测/性能测试
InnoDB和MyISAM简介 MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是Indexed Sequential Access Method (有索引的 顺序访问方法) 的缩写 ...
- linux内核中send与recv函数详解
Linux send与recv函数详解 1.简介 #include <sys/socket.h> ssize_t recv(int sockfd, void *buff, size_t n ...
- QT在Windows控制台下输出
原地址:http://blog.csdn.net/fjb2080/article/details/9013047 在windows的控制台下输出,需要在pro文件中加入: CONFIG += cons ...
- C++ 观察者模式样例
C++ 观察者模式样例 #include <iostream> #include <set> #include <string> using namespace s ...
- asp.net笔试题
1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private : 私有成员, 在类的内部才可以访问. protected : 保护成 ...