LCS的java算法---考虑可能有多个相同的最长公共子串
来源:互联网 发布:曾经流行的网络词语 编辑:程序博客网 时间:2024/05/20 01:44
LCS(Longest Common Subsequence) 就是求两个字符串最长公共子串的问题。
比如:
String str1 = new String("adbccadebbca");
String str2 = new String("edabccadece");
str1与str2的公共子串就是bccade.
下面是字符串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
1 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 1 0 0 0 1 1 0 0 1 0 0 0
1 0 1 0 1 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
1 0 2 0 1 0 1 0 0 0 0 0 1 0 0
0 2 0 0 0 0 0 0 0 1 1 0 0 0 0
1 0 3 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 5 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 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());
}
}
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的java算法---考虑可能有多个相同的最长公共子串
- 最长公共子串LCS算法
- 最长公共子串LCS算法
- LCS算法求最长公共子串
- LCS算法求最长公共子串
- LCS/最长公共子串算法分析
- 最长公共子串LCS算法
- 常考的经典算法--最长公共子序列(LCS)与最长公共子串(DP)
- LCS最长公共子序列的理解
- LCS算法实现 求两个字符串中间最长的公共子串
- 最长公共子序列LCS和最长回文子序列的动态规划算法
- 求两个字符串的最长公共子串(LCS)
- 求两个字符串的最长公共子串(LCS)
- 求两个字符串的最长公共子串(LCS)
- LCS算法的概述及由来(LCS)最长公共子序列
- 算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列
- LCS:最长公共子串
- 最长公共子串LCS
- JOB 用法小结(转载)
- VXML语言演示
- 取得指定表的指定字段下一个可用的编号
- [转帖]程序员的成功之道
- php数组的重组及多级下拉菜单
- LCS的java算法---考虑可能有多个相同的最长公共子串
- JdbcTemplate使用SQL语句查询
- 金额转换成中文大写
- oracle sql性能优化网摘
- 今天,我开博了
- 对齐的方式
- java中定时器timer类的实现和源代码
- 处理SQL语句中的单引号
- WEB定时器-Timer