建設(shè)部網(wǎng)站八大員查詢app推廣平臺(tái)排行榜
1143. 最長(zhǎng)公共子序列
給定兩個(gè)字符串 text1 和 text2,返回這兩個(gè)字符串的最長(zhǎng) 公共子序列 的長(zhǎng)度。如果不存在 公共子序列 ,返回 0 。
一個(gè)字符串的 子序列 是指這樣一個(gè)新的字符串:它是由原字符串在不改變字符的相對(duì)順序的情況下刪除某些字符(也可以不刪除任何字符)后組成的新字符串。
- 例如,“ace” 是 “abcde” 的子序列,但 “aec” 不是 “abcde” 的子序列。
兩個(gè)字符串的 公共子序列 是這兩個(gè)字符串所共同擁有的子序列。
示例 1:
輸入:text1 = “abcde”, text2 = “ace”
輸出:3
解釋:最長(zhǎng)公共子序列是 “ace” ,它的長(zhǎng)度為 3 。
示例 2:
輸入:text1 = “abc”, text2 = “abc”
輸出:3
解釋:最長(zhǎng)公共子序列是 “abc” ,它的長(zhǎng)度為 3 。
示例 3:
輸入:text1 = “abc”, text2 = “def”
輸出:0
解釋:兩個(gè)字符串沒有公共子序列,返回 0 。
提示:
- 1 <= text1.length, text2.length <= 1000
- text1 和 text2 僅由小寫英文字符組成。
思路:(動(dòng)態(tài)規(guī)劃)
對(duì)于兩個(gè)子序列 S1S1S1 和 S2S2S2,找出它們最長(zhǎng)的公共子序列。
定義一個(gè)二維數(shù)組 dp 用來存儲(chǔ)最長(zhǎng)公共子序列的長(zhǎng)度,其中 dp[i][j] 表示 S1S1S1 的前 i 個(gè)字符與 S2S2S2 的前 j 個(gè)字符最長(zhǎng)公共子序列的長(zhǎng)度。考慮 S1iS1_iS1i?與 S2jS2_jS2j? 值是否相等,分為兩種情況:
- 當(dāng) S1i==S2jS1_i == S2_jS1i?==S2j? 時(shí),那么就能在 S1S1S1 的前 i -1 個(gè)字符與 S2S2S2 的前 j -1 個(gè)字符最長(zhǎng)公共子序列的基礎(chǔ)上再加上 S1iS1_iS1i? 這個(gè)值,最長(zhǎng)公共子序列長(zhǎng)度加 1,即 dp[i][j] = dp[i-1][j-1] + 1。
- 當(dāng) S1i!=S2jS1_i != S2_jS1i?!=S2j? 時(shí),此時(shí)最長(zhǎng)公共子序列為 S1S1S1的前 i -1 個(gè)字符和 S2 的前 j 個(gè)字符最長(zhǎng)公共子序列,或者 S1S1S1 的前 i 個(gè)字符和 S2S2S2 的前 j -1 個(gè)字符最長(zhǎng)公共子序列,取它們的最大者,即 dp[i][j] = max{ dp[i-1][j], dp[i][j-1] }。
綜上,最長(zhǎng)公共子序列的 狀態(tài)轉(zhuǎn)移方程 為:
dp[i][j]={dp[i?1][j?1]+1S1i==S2jmax?(dp[i?1][j],dp[i][j?1])S1i<>S2jd p[i][j]=\left\{\begin{array}{rr} d p[i-1][j-1]+1 & S 1_{i}==S 2_{j} \\ \max (d p[i-1][j], d p[i][j-1]) & S 1_{i}<>S 2_{j} \end{array}\right.dp[i][j]={dp[i?1][j?1]+1max(dp[i?1][j],dp[i][j?1])?S1i?==S2j?S1i?<>S2j??
對(duì)于長(zhǎng)度為 m 的序列 S1 和長(zhǎng)度為 n 的序列 S2,dp[m][n] 就是序列 S1 和序列 S2 的最長(zhǎng)公共子序列長(zhǎng)度。
與最長(zhǎng)遞增子序列 相比,最長(zhǎng)公共子序列有以下不同點(diǎn):
- 針對(duì)的是兩個(gè)序列,求它們的最長(zhǎng)公共子序列。
- 在最長(zhǎng)遞增子序列中,dp[i] 表示以 SiS_iSi? 為結(jié)尾的最長(zhǎng)遞增子序列長(zhǎng)度,子序列必須包含 SiS_iSi? ;在最長(zhǎng)公共子序列中,dp[i][j] 表示 S1 中前 i 個(gè)字符與 S2 中前 j 個(gè)字符的最長(zhǎng)公共子序列長(zhǎng)度,不一定包含 S1iS1_iS1i? 和 S2jS2_jS2j?。
- 在求最終解時(shí),最長(zhǎng)公共子序列中 dp[m][n] 就是最終解,而最長(zhǎng)遞增子序列中 dp[n] 不是最終解,因?yàn)橐?SnS_nSn? 為結(jié)尾的最長(zhǎng)遞增子序列不一定是整個(gè)序列最長(zhǎng)遞增子序列,需要遍歷一遍 dp 數(shù)組找到最大者。
代碼:(Java)
public class LongestCommonSubsequence {public static void main(String[] args) {// TODO Auto-generated method stubString text1 = "abcde";String text2 = "ace";System.out.println(longestCommonSubsequence(text1,text2));}public static int longestCommonSubsequence(String text1, String text2) {int m = text1.length();int n = text2.length();int[][] dp = new int[m + 1][n + 1];for(int i = 1; i <= m; i++) {for(int j = 1; j <= n; j++) {if(text1.charAt(i - 1) == text2.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1] + 1;}else {dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);}}}return dp[m][n];}
}
運(yùn)行結(jié)果:
復(fù)雜度分析:
- 時(shí)間復(fù)雜度:O(mn)O(mn)O(mn),需要遍歷兩個(gè)字符串。
- 空間復(fù)雜度:O(mn)O(mn)O(mn),需要m*n的二維數(shù)組。
注:僅供學(xué)習(xí)參考!
題目來源:力扣。