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. HDOJ1073(gets 应用)

    练习操作字符串的好题. #include<cstdio> #include<algorithm> #include<cstring> using namespace ...

  2. POJ3126Prime Path(BFS)

    #include"cstdio" #include"queue" #include"cstring" using namespace std ...

  3. uboot搬移部分和重定位部分的代码分析

    来看一下搬移部分和重定位部分的代码: relocate: /* 把U-BOOT重新定位到RAM*/          //r0=0; adr r0, _start /* r0是代码的当前位置*/ ld ...

  4. Elasticsearch2.x --DeleteByQuery

    一.安装插件 要删除某个索引的一个type下的所有文档,相当于关系型数据库中的清空表操作.查阅了一些资料可以通过Delete-by-Query插件删除,首先使用插件管理器安装Delete-by-Que ...

  5. android studio在windows上设置git/ssh

    windows果然是与众不同的,凡事都要那么麻烦一点点(当然..是对程序员来说..) 一开始,我想用cygwin里的git,就省得我再多装一套软件,配置也可以统一,但事实证明不行 在android s ...

  6. 超级台阶 (NYOJ—76)

    很简单的高中数学题,写出来主要是提醒自己,写完递推公式(尤其是公式)一定要检查多遍. #include<stdio.h> #include<string.h> int M; i ...

  7. loj#6053. 简单的函数(Min_25筛)

    传送门 题解 \(Min\_25\)筛有毒啊--肝了一个下午才看懂是个什么东西-- \(zsy\)巨巨强无敌-- //minamoto #include<bits/stdc++.h> #d ...

  8. 洛谷P5170 【模板】类欧几里得算法(数论)

    传送门 此题剧毒,公式恐惧症患者请直接转去代码→_→ 前置芝士 基本数论芝士 题解 本题就是要我们求三个函数的值 \[f(a,b,c,n)=\sum_{i=0}^n \left\lfloor\frac ...

  9. windows severs 2008r2 180天激活

    无需破解:Windows Server 2008 R2 至少免费使用 900天 1.首先安装后,有一个180天的试用期. 2.在180天试用期即将结束时,使用下面的评估序列号激活Svr 2008 R2 ...

  10. mysql安装等操作

    CentOS 6.5系统中安装配置MySQL数据库 卸载掉原有mysql rpm -qa | grep mysql // 这个命令就会查看该操作系统上是否已经安装了mysql数据库 rpm -e my ...