给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。
示例 1:
输入: “sea”, “eat”
输出: 2
解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"
方法 3:最长公共子序列 - 动态规划 [Accepted]
算法
另一个获得 lcs 值的办法是动态规划。我们来看看它的实现思想和具体方法。
我们使用一个二维数组 dp,dp[i][j] 表示 s1 前 i 个字符和 s2 前 j 个
字符中最长公共子序列。我们逐行填充 dp 数组。
对于每一个 dp[i][j],我们有 2 种选择:
字符 s1[i-1] 和 s2[j-1] 匹配,那么 dp[i][j] 会比两个字符串分别
考虑到前 i−1 个字符 和 j-1 个字符的公共子序列长度多 1 。所以 dp[i][j] 被更
新为 dp[i][j] = dp[i-1][j-1] + 1。注意到 dp[i−1][j−1] 已经被求解过了,
所以可以直接使用。
字符 s1[i-1] 和 s2[j-1] 不匹配,这种情况下我们不能直接增加已匹配子序列的长度,
但我们可以将之前已经求解过的最长公共子序列的长度作为当前最长公共子序列的长度。
但是我们应该选择哪一个呢?事实上此时我们有 2 种选择。
我们可以删除 s1 或者 s2 的最后一个字符然后将对应的 dp 数组的值作比较,
也就是取 dp[i-1][j] 和 dp[i][j-1] 的较大值。
最后,与前面方法类似的,我们获得删除次数 m + n - 2*dp[m][n] ,
其中m和n分别是 s1 和 s2 的字符串长度,,dp[m][n]是两个字符串的最长公共子序列。
class Solution {
public int minDistance(String word1, String word2) {
int rows = word1.length();
int cols = word2.length();
int[][] dp = new int[rows + 1][cols + 1];
for (int i = 0; i < rows + 1; i++) {
for (int j = 0; j < cols + 1; j++) {
if (i == 0 || j == 0) {
continue;
}
if (word1.charAt(i - 1) == word2.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 rows + cols - 2 * dp[rows][cols];
}
}