LCS(Longest Common Subsequence)
http://blog.csdn.net/zztfj/article/details/6157429
LCS(Longest Common Subsequence) 就是求两个字符串最长公共子串的问题。
比如:
String str1 = new String("adbccadebbca");
String str2 = new String("edabccadece");
str1与str2的公共子串就是bccade.
解法就是用一个矩阵来记录两个字符串中所有位置的两个字符之间的匹配情况,若是匹配则为1,否则为0。然后求出对角线最长的1序列,其对应的位置就是最长匹配子串的位置.
下面是字符串21232523311324和字符串312123223445的匹配矩阵,前者为X方向的,后者为Y方向的。不难找到,红色部分是最长的匹配子串。通过查找位置我们得到最长的匹配子串为:21232
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
0 1 0 0 0 0 0 0 0 1 1 0 0 0 0
0 1 0 1 0 1 0 0 0 0 0 1 0 0
0 1 0 0 0 0 0 0 0 1 1 0 0 0 0
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0
1 0 1 0 0 1 0 0 0 0 0 1 0 0
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
但是在0和1的矩阵中找最长的1对角线序列又要花去一定的时间。通过改进矩阵的生成方式和设置标记变量,可以省去这部分时间。下面是新的矩阵生成方式:
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0
0 1 0 0 0 0 0 0 0 2 1 0 0 0 0
0 2 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 1 1 0 0 0 0
1 0 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 4 0 0 0 2 1 0 0 1 0 0 0
1 0 1 0 0 1 0 0 0 0 0 2 0 0
1 0 1 0 1 0 1 0 0 0 0 0 1 0 0
0 0 0 2 0 0 0 2 1 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
当字符匹配的时候,我们并不是简单的给相应元素赋上1,而是赋上其左上角元素的值加一。我们用两个标记变量来标记矩阵中值最大的元素的位置,在矩阵生成的过程中来判断当前生成的元素的值是不是最大的,据此来改变标记变量的值,那么到矩阵完成的时候,最长匹配子串的位置和长度就已经出来了。具体算法如下:
public static void getLCString(char[] str1, char[] str2)
{ int str1Lent=str1.length;
int str2Lent=str2.length;
int[][] tempArray=new int[str1Lent][str2Lent];
int arrayLegth=Math.max(str1.length, str2.length); int[] beginMaxIndex=new int[arrayLegth]; //字符串起始坐标
int[] endMaxIndex=new int[arrayLegth]; //字符串介绍坐标
//例如 beginMaxIndex[0]=1,beginMaxIndex=3,代表str2的起始坐标的字串为1结束为3=dbb int maxLenth=0;
int moveIndex=0;//相同长度的字符个数
for(int i=0;i<str1.length;i++){
for(int j=0;j<str2.length;j++){
if(str1[i]==str2[j]){
if(i==0||j==0){
tempArray[i][j]=1;
}else{
tempArray[i][j]=tempArray[i-1][j-1]+1;
}
if(tempArray[i][j]>maxLenth){
maxLenth=tempArray[i][j];
endMaxIndex[0]=j+1;
beginMaxIndex[0]=j+1-maxLenth;
moveIndex=0; }else if(maxLenth==tempArray[i][j]){
moveIndex++;
endMaxIndex[moveIndex]=j+1;
beginMaxIndex[moveIndex]=j+1-maxLenth;
}
}
}
}
if(moveIndex>0){
for(int i=0;i<moveIndex;i++){
int start=beginMaxIndex[i];
int end=endMaxIndex[i]; for(int j=start;j<end;j++){
System.out.print(str2[j]);
}
System.out.println("");
}
}
} public static void main(String[] args) { String str1 = new String("adbba1234");
String str2 = new String("adbbf1234sa");
getLCString(str1.toCharArray(),str2.toCharArray());
}
这样做速度比较快,但是花的空间太多。我们注意到在改进的矩阵生成方式当中,每生成一行,前面的那一行就已经没有用了。因此我们只需使用一维数组即可。最终的代码如下:
package lz77decompress; public class LCString2 { public static void getLCString(char[] str1, char[] str2)
{
int i,j;
int len1,len2;
len1 = str1.length;
len2 = str2.length;
int maxLen = len1 > len2?len1:len2;
int[] max = new int[maxLen];
int[] maxIndex = new int[maxLen];
int[] c = new int[maxLen]; for (i = 0; i < len2 ; i++)
{
for (j = len1 -1; j >= 0; j--)
{
if (str2[i] == str1[j])
{
if ( ( i == 0) || (j == 0) )
c[j] = 1;
else
c[j] = c[j-1] + 1;
}
else
{
c[j] = 0;
} if (c[j] > max[0])
{ //如果是大于那暂时只有一个是最长的,而且要把后面的清0;
max[0] = c[j];
maxIndex[0] = j; for (int k = 1; k < maxLen; k++)
{
max[k] = 0;
maxIndex[k] = 0;
}
}
else if (c[j] == max[0])
{ //有多个是相同长度的子串
for (int k = 1; k < maxLen; k++)
{
if (max[k] == 0)
{
max[k] = c[j];
maxIndex[k] = j;
break; //在后面加一个就要退出循环了
} }
}
}
} for (j = 0; j < maxLen; j++)
{
if (max[j] > 0)
{
System.out.println("第" + (j + 1) + "个公共子串:");
for (i = maxIndex[j] - max[j] + 1; i <= maxIndex[j]; i++)
System.out.print(str1[i]);
System.out.println(" ");
}
}
} public static void main(String[] args) { String str1 = new String("adbba1234");
String str2 = new String("adbbf1234sa");
getLCString(str1.toCharArray(),str2.toCharArray());
}
}
LCS(Longest Common Subsequence)的更多相关文章
- 动态规划之最长公共子序列LCS(Longest Common Subsequence)
一.问题描述 由于最长公共子序列LCS是一个比较经典的问题,主要是采用动态规划(DP)算法去实现,理论方面的讲述也非常详尽,本文重点是程序的实现部分,所以理论方面的解释主要看这篇博客:http://b ...
- LCS(Longest Common Subsequence)最长公共子序列
最长公共子序列(LCS)是一个在一个序列集合中(通常为两个序列)用来查找所有序列中最长子序列的问题.这与查找最长公共子串的问题不同的地方是:子序列不需要在原序列中占用连续的位置 .最长公共子序列问题是 ...
- 动态规划求最长公共子序列(Longest Common Subsequence, LCS)
1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...
- LCS(Longest Common Subsequence 最长公共子序列)
最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...
- UVA 10405 Longest Common Subsequence (dp + LCS)
Problem C: Longest Common Subsequence Sequence 1: Sequence 2: Given two sequences of characters, pri ...
- 最长公共字串算法, 文本比较算法, longest common subsequence(LCS) algorithm
''' merge two configure files, basic file is aFile insert the added content of bFile compare to aFil ...
- Longest common subsequence(LCS)
问题 说明该问题在生物学中的实际意义 Biological applications often need to compare the DNA of two (or more) different ...
- LintCode Longest Common Subsequence
原题链接在这里:http://www.lintcode.com/en/problem/longest-common-subsequence/ 题目: Given two strings, find t ...
- Longest Common Subsequence
Given two strings, find the longest common subsequence (LCS). Your code should return the length of ...
随机推荐
- redhat 安装lamp
安装Apache yum install httpd 安装MySql yum install mysql mysql-server 安装php yum install php 安装php的mysql模 ...
- 【转】 Pro Android学习笔记(三五):Menu(6):XML方式 & PopUp菜单
目录(?)[-] 利用XML创建菜单 XML的有关属性 onClick事件 Pop-up菜单 利用XML创建菜单 在代码中对每个菜单项进行设置,繁琐且修改不灵活,不能适配多国语言的要求,可以利用资源进 ...
- VC6.0 工程转到VS2010一些问题的描述及解决方法
下列为VC6.0 工程转到VS2008一些问题的描述及解决方法 //////////////////////////////////////////////////////////////////// ...
- 利用Admin-LTE项目搭建自己前端的开发框架模板
1 完整版本 1.1 下载admin-lte项目源代码 github下载地址:点击前往 三少云盘地址:点击前往 1.2 查看admin-lte精简主页源代码 页面地址:点击前往 注意:由源代码可以知道 ...
- 各版本Google浏览器下载地址
各版本谷歌浏览器下载地址 https://www.chromedownloads.net/chrome64win/
- 3. 文件上传靶机实战(附靶机跟writeup)
upload-labs 一个帮你总结所有类型的上传漏洞的靶场 文件上传靶机下载地址:https://github.com/c0ny1/upload-labs 运行环境 操作系统:推荐windows ...
- OpenStack基础知识-tox的详解介绍
1.tox简介 tox是通用的虚拟环境管理和测试命令行工具.tox能够让我们在同一个Host上自定义出多套相互独立且隔离的python环境,每套虚拟环境中可能使用了不同的 Python 拦截器/环境变 ...
- [CentOS7] iconv编程转换
声明:本文主要总结自:鸟哥的Linux私房菜-第九章.vim 程式編輯器,如有侵权,请通知博主 (-- 源自鸟哥的私房菜) 首先用Notepad++新建个文件来做这个实验,在Windows平台下新建个 ...
- ARC085E(最小割规划【最大流】,Dinic当前弧优化)
#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll inf=0x3f3f3f3f;int cn ...
- 2017-10-26 NOIP模拟赛
三分咲 #include<iostream> #include<cstdio> #include<ctime> using namespace std; int n ...