- 上一篇 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 羣,
我們,
一起進步!