Day05 动态规划-编辑距离问题
莱文斯坦距离
- 允许增加、删除、替换字符这三个编辑操作。
- 莱温斯坦距离的大小,表示两个字符串差异的大小
- 思路:
- 回溯。取a,b两指针分别指向s1、s2。
- 当a,b指针位置相同时,继续向后遍历
- 不同时,回溯三种情况。增加节点、删除节点、替换节点
class Solution {
public int minDistance(String word1, String word2) {
return dfs(word1, word2, 0, 0);
}
private int dfs(String word1, String word2, int a, int b) {
if (a > word1.length() - 1) {
return Math.max(0,word2.length() - b);
}
if (b > word2.length() - 1) {
return Math.max(0,word1.length() - a);
}
char target = word1.charAt(a);
char c = word2.charAt(b);
if (target == c) return dfs(word1, word2, a + 1, b + 1);
else {
return Math.min(
dfs(word1, word2, a + 1, b + 1),
Math.min(dfs(word1, word2, a + 1, b), dfs(word1, word2, a, b + 1))
) + 1;
}
}
}
- 优化-记忆化搜索
- 回溯超时-有很多重叠子问题。
- 引入dp数组。dp[i][j]代表i、j节点匹配的记录结果。
class Solution {
int[][] dp;
public int minDistance(String word1, String word2) {
dp = new int[word1.length()][word2.length()];
return dfs(word1, word2, 0, 0);
}
private int dfs(String word1, String word2, int a, int b) {
if (a > word1.length() - 1) {
return Math.max(0,word2.length() - b);
}
if (b > word2.length() - 1) {
return Math.max(0,word1.length() - a);
}
if (dp[a][b] != 0) return dp[a][b];
char target = word1.charAt(a);
char c = word2.charAt(b);
if (target == c) dp[a][b] = dfs(word1, word2, a + 1, b + 1);
else {
dp[a][b] = Math.min(
dfs(word1, word2, a + 1, b + 1),
Math.min(dfs(word1, word2, a + 1, b), dfs(word1, word2, a, b + 1))
) + 1;
}
return dp[a][b];
}
}
- 动态规划
class Solution {
public int minDistance(String word1, String word2) {
int m = word1.length();
int n = word2.length();
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= n; i++) {
dp[0][i] = i;
}
for (int i = 1; i <= m; i++) {
dp[i][0] = i;
}
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = Math.min(
dp[i - 1][j],
Math.min(dp[i][j - 1], dp[i - 1][j - 1])
) + 1;
}
}
}
return dp[m][n];
}
}
- 只允许增加、删除字符这两个编辑操作。
- 最长公共子串的大小,表示两个字符串相似程度的大小
class Solution {
public int longestCommonSubsequence(String text1, String text2) {
int m = text1.length();
int n = text2.length();
int[][] dp = new int[m + 1][n + 1];
for (int j = 1; j <= n; j++) {
if (text1.charAt(0) == text2.charAt(j - 1)){
dp[1][j] = 1;
}else {
dp[1][j] = dp[1][j - 1];
}
}
for (int i = 1; i <= m; i++) {
if (text1.charAt(i - 1) == text2.charAt(0)){
dp[i][1] = 1;
}else {
dp[i][1] = dp[i - 1][1];
}
}
for (int i = 2; i <= m; i++) {
char target = text1.charAt(i - 1);
for (int j = 2; j <= n; j++) {
if (text2.charAt(j - 1) == target){
dp[i][j] = dp[i - 1][j - 1] + 1;
}else {
dp[i][j] = Math.max(dp[i][j - 1],dp[i - 1][j]);
}
}
}
return dp[m][n];
}
}