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)的更多相关文章

  1. 动态规划之最长公共子序列LCS(Longest Common Subsequence)

    一.问题描述 由于最长公共子序列LCS是一个比较经典的问题,主要是采用动态规划(DP)算法去实现,理论方面的讲述也非常详尽,本文重点是程序的实现部分,所以理论方面的解释主要看这篇博客:http://b ...

  2. LCS(Longest Common Subsequence)最长公共子序列

    最长公共子序列(LCS)是一个在一个序列集合中(通常为两个序列)用来查找所有序列中最长子序列的问题.这与查找最长公共子串的问题不同的地方是:子序列不需要在原序列中占用连续的位置 .最长公共子序列问题是 ...

  3. 动态规划求最长公共子序列(Longest Common Subsequence, LCS)

    1. 问题描述 子串应该比较好理解,至于什么是子序列,这里给出一个例子:有两个母串 cnblogs belong 比如序列bo, bg, lg在母串cnblogs与belong中都出现过并且出现顺序与 ...

  4. LCS(Longest Common Subsequence 最长公共子序列)

    最长公共子序列 英文缩写为LCS(Longest Common Subsequence).其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,且是所有符合此条件序列中最长的,则 S 称为已 ...

  5. UVA 10405 Longest Common Subsequence (dp + LCS)

    Problem C: Longest Common Subsequence Sequence 1: Sequence 2: Given two sequences of characters, pri ...

  6. 最长公共字串算法, 文本比较算法, longest common subsequence(LCS) algorithm

    ''' merge two configure files, basic file is aFile insert the added content of bFile compare to aFil ...

  7. Longest common subsequence(LCS)

    问题 说明该问题在生物学中的实际意义 Biological applications often need to compare the DNA of two (or more) different ...

  8. LintCode Longest Common Subsequence

    原题链接在这里:http://www.lintcode.com/en/problem/longest-common-subsequence/ 题目: Given two strings, find t ...

  9. Longest Common Subsequence

    Given two strings, find the longest common subsequence (LCS). Your code should return the length of  ...

随机推荐

  1. C# 利用Xsd验证xml

    最近做项目时,用到了xml的序列化与反序列化, 发现最好用xsd来验证xml, 因为反序列化xml不校验xsd. 方法:xmlData变量为xml字符串 MemoryStream ms = new M ...

  2. C++ ORM ODB入门

    1.ORM ORM, Object Relational Mapping, 对象关系映射,用来将基于对象的数据结构映射到SQL的数据结构中.即将基于对象的数据映射到关系表中的字段,然后我们可以通过对象 ...

  3. 【转】 Pro Android学习笔记(六二):Preferences(6):header

    目录(?)[-] 代码实现 header xml文件 在前面的例子,我们主要学习了PreferenceScreen的xml如何写,preference有哪些类型.在代码中,我们为了不提示warning ...

  4. 【转】Pro Android学习笔记(十二):了解Intent(下)

    解析Intent,寻找匹配Activity 如果给出component名字(包名.类名)是explicit intent,否则是implicit intent.对于explicit intent,关键 ...

  5. AI-Info-Micron-Menu:About Micron

    ylbtech-AI-Info-Micron-Menu:About Micron 将数据带入生活 美光科技的存储技术帮助将海量数据化为宝贵见解,重新定义世界使用信息的方式. 1.返回顶部 1. 公司简 ...

  6. Mybatis+Mysql 返回主键的值

    需求:使用MyBatis往MySQL数据库中插入一条记录后,需要返回该条记录的自增主键值. 方法:在mapper中指定keyProperty属性,示例如下: <insert id="i ...

  7. [Uva10641]Barisal Stadium(区间dp)

    题意:按照顺时针给出操场的周边点,然后给出周围可以建设照明灯的位置,以及在该位置建设照明灯的代价,照明灯照射的范围与操场的边界相切,现在要求一个最小的花费,要求操场的所有边都被照射到. 解题关键:预处 ...

  8. [tyvj1860]后缀数组

    题目链接:http://www.tyvj.cn/p/1860 解题关键:模板题.贴一个代码详解 http://www.cnblogs.com/staginner/archive/2012/02/02/ ...

  9. CODING 代码托管架构升级之路

    本文为 CODING 创始团队成员王振威在『CODING 技术小馆:上海站』的演讲实录. CODING 技术小馆,是由国内专业的一站式软件服务平台 CODING 主办的一系列技术沙龙.将邀请数位业内知 ...

  10. 使用Cors后台设置WebAPI接口跨域访问

    昨天根据项目组前端开发工程师反映,在浏览器端无法直接使用ajax访问后台接口获取数据,根据他的反映,我查阅了相关跨域的解决方案: 一:使用jsonP,但是jsonP只能使用GET请求,完全不符合我项目 ...