- 上一篇 LeetCode 我们用暴力法求解的最长回文子序列的问题, 但是很可惜我们的时间复杂度太高, 不被接受, 今天我们本着另一个思想再次求解此问题, 但是由于新的算法需要获取两个字符串换的公共子串, 因此, 我们首先介绍一个新的问题:
获取两个字符串的最长公共连续子串.
例如:
输入:
“abcfg” 与 “kmlozazui”
“aaaaa” 与 “aaaaaaaaa”
“abcdefedcba” 与 “abcdefedcba”输出:
“a”
“aaaaa”
“abcdefedcba”
暴力求解法就不介绍了(以后暴力求解法也不会出现在博人中, 除非有必要 ), 大家都能想到, 这里介绍一种动态规划 DP 算法求解最长公共子串.
- 首先根据 str1 和 str2 初始化一个表 rc[str1.length][str2.length], 其初始值值均为 0;
- 遍历每一个行和列, 如果
str1[i] == str2[j]
, 那么rc[i][j] = rc[i - 1][j - 1] + 1
. 这样最长公共连续子串就是 rc 中值最大的单元格所对应的子串.
也可以如果
str1[i] == str2[j]
, 那么rc[i][j] = 1
. 这样最长公共连续子串就是 rc 中值为 1 且长度最长的对角连线所对应的子串.
Talk is cheap, show me the code…
package com.jackli.solution;
/**
* @Description: LCS: 获取一个字符中的最长公共连续子串.
* @Warning:
* @Author: Jack Li
* @Package: question005 - LongestSubString
* @Date: Nov 30, 2019 11:39:17 PM
* @Version: 1.0.0
* @TimeComplexity: Required[*] ---- Current[O(n^2)]
* @ExecuteResult: Success!
* @Status: Accepted
*/
public class LongestSubString {
public static void main(String[] args) {
System.out.println(longestSubstring("", null));
System.out.println(longestSubstring("", ""));
System.out.println(longestSubstring("abc", "defg"));
System.out.println(longestSubstring("abcfg", "kmlozazui"));
System.out.println(longestSubstring("aaaaa", "aaaaaaaaa"));
System.out.println(longestSubstring("abcdefedcba", "abcdefedcba"));
}
/**
* @Description: 定义一个以 str1 为行, 以 str2 为 列的
* @Warning:
* @Author: Jack Li
* @Date: Nov 30, 2019 11:56:16 PM
* @Version: 1.0.0
* @param str1
* @param str2
* @return
*/
public static String longestSubstring(String str1, String str2) {
if(str1 == null || str1.isEmpty() || str2 == null || str2.isEmpty()) {
return null;
}
String result = null;
// 初始化一个表用于记录 str1 和 str2 的相同字符的坐标与长度
int[][] rc = new int[str1.length()][str2.length()];
int leftTop;
int subLength = 0, endIndexByStr1 = 0;
for(int i = 0; i < str1.length(); i++) {
for(int j = 0; j < str2.length(); j++) {
if(str1.charAt(i) == str2.charAt(j)) {
// 获取左上角的值
leftTop = 0;
if(i > 0 && j > 0) {
leftTop = rc[i - 1][j - 1];
}
rc[i][j] = leftTop + 1;
if(rc[i][j] > subLength) {
subLength = rc[i][j];
endIndexByStr1 = i;
}
}
}
}
// 获取最长子序列
if(subLength > 0) {
result = str1.substring(endIndexByStr1 - subLength + 1, endIndexByStr1 + 1);
}
return result;
}
}
每文一骚
We’re in the fight of our lives.
我们都在生命中奋斗着.
没过瘾?
关注我获取更多技术干货
————————————
扫一扫关注公众号, 加入 QQ 群,
我们,
一起进步!