系列文章导引
开源项目
本系列所有文章都将会收录到GitHub
中统一收藏与管理,欢迎ISSUE
和Star
。
GitHub传送门:Kiner算法算题记
1143. 最长公共子序列
解题思路
- 递推状态:我们最长公共子序列的长度取决于以第
i-1
个字符作为结尾的A
字符串与以第j-1
个字符作为结尾的B
字符串公共子串长度。因此,我们的递推状态应为:dp[i,j]
,代表:A串长度为i位,B串长度为j位的最长公共子序列的长度。 - 递推公式(状态转移方程):当我们
A
串第i-1
个字符与B
串第j-1
个字符相等时,即两个字符串分别以i-1
位和j-1
位对齐时,最长公共字串的长度应该为:dp[i-1][j-1] + 1
,dp[i-1][j-1]
代表我们A
串第i-1
个字符与B
串第j-1
个字符作为结尾的最长公共字串的长度,再加上当前这个相同的字符串的长度1。而当我们A
串第i-1
个字符与B
串第j-1
个字符不相等时,我们公共字串的长度取决于分别以i-1
位与j
位作为结尾的A
、B
串最长公共字串的长度和分别以i
位与j-1
位作为结尾的A
、B
串最长公共字串的长度的最大值。综合上述两个条件,我们得到递推公式为:最后一位对齐时:dp[i][j] = dp[i-1][j-1] + 1;最后一位不对齐时:dp[i][j] = max(dp[i-1][j],dp[i][j-1])
- 边界条件:当整个字符串都不匹配时,最长公共子序列的长度为0,我们初始时可以将dp数组中每个位置都初始化为0,后续操作也更加方便。
代码演示
function longestCommonSubsequence(text1: string, text2: string): number {
let n = text1.length;
let m = text2.length;
// 初始化dp数组为(n+1)*(m+1)的二维数组,并在每一位初始填充为0
const dp = new Array(n + 1).fill(0).map(() => new Array(m + 1).fill(0));
for(let i = 1; i <= n; i++) {
for(let j = 1; j <= m; j++) {
// 如果a串的最后一位与b串的最后一位相等
if(</