最长公共子序列 & 最长公共子串的区别:找两个字符串的最长公共子串,这个子串要求在原字符串中是连续的。而最长公共子序列则并不要求连续
这两个都可以使用动态规划解决,但是思路不太一样。
我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?直接举个例子吧:”bab”和”caba”(当然我们现在一眼就可以看出来最长公共子串是”ba”或”ab”)
b a b
c 0 0 0
a 0 1 0
b 1 0 1
a 0 1 0
我们看矩阵的斜对角线最长的那个就能找出最长公共子串。不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。
b a b
c 0 0 0
a 0 1 0
b 1 0 2
a 0 2 0
这两个都可以使用动态规划解决,但是思路不太一样。
我们采用一个二维矩阵来记录中间的结果。这个二维矩阵怎么构造呢?直接举个例子吧:”bab”和”caba”(当然我们现在一眼就可以看出来最长公共子串是”ba”或”ab”)
b a b
c 0 0 0
a 0 1 0
b 1 0 1
a 0 1 0
我们看矩阵的斜对角线最长的那个就能找出最长公共子串。不过在二维矩阵上找最长的由1组成的斜对角线也是件麻烦费时的事,下面改进:当要在矩阵是填1时让它等于其左上角元素加1。
b a b
c 0 0 0
a 0 1 0
b 1 0 2
a 0 2 0
这样矩阵中的最大元素就是 最长公共子串的长度。
具体实例及实现代码如下所示:
/** * @Title: LongestCommomSubString.java * @Package dynamicprogramming * @Description: TODO * @author peidong * @date 2017-6-13 上午8:41:48 * @version V1.0 */ package dynamicprogramming; /** * @ClassName: LongestCommomSubString * @Description:最长公共子串 * @date 2017-6-13 上午8:41:48 * */ public class LongestCommomSubString { /** * * @Title: longestCommonSubString * @Description: 动态规划求解最长公共子串 * @param str1 * @param str2 * @return * @return String * @throws */ public static String longestCommonSubString(String str1, String str2){ //创建变量保存公共子串,此处不能用String,需要改变 StringBuilder sb = new StringBuilder(); //边界条件判断 if(str1 == null || str1.isEmpty() || str2 == null || str2.isEmpty()) return ""; //创建状态转移矩阵,保存子串长度 int[][] tc = new int[str1.length()][str2.length()]; //定义变量保存最长字符串长度 int maxLen = 0; //定义变量保存最长子串起始位置 int lastSubsBegin = 0; //构建状态转移矩阵 for(int i = 0; i < str1.length(); i++){ for(int j = 0; j < str2.length(); j++){ if(str1.charAt(i) == str2.charAt(j)){ if(i == 0 || j == 0) tc[i][j] = 1; else tc[i][j] = 1 + tc[i-1][j-1]; if(tc[i][j] > maxLen){ maxLen = tc[i][j]; //记录此时子串在str1中的起始位置 int thisBegin = i - tc[i][j] + 1; //如果是同一个子串 if(lastSubsBegin == thisBegin) sb.append(str1.charAt(i)); else{//不是同一个子串重新生成 lastSubsBegin = thisBegin; sb = new StringBuilder(); sb.append(str1.substring(lastSubsBegin, i + 1)); } } } } } return sb.toString(); } /** * @Title: main * @Description: 测试用例 * @param args * @return void * @throws */ public static void main(String[] args) { // TODO Auto-generated method stub String str1 = "I love python!"; String str2 = "love python I do"; String str = longestCommonSubString(str1, str2); System.out.println("两字符串的最长公共子串为:" + str); System.out.println("最长公共子串的长度为:" + str.length()); } }