好难啊 字符串动态规划的好多题我都不会
标签 |
---|
字符串 |
动态规划 |
题目
https://leetcode-cn.com/problems/edit-distance/
分析
本质不同的操作实际上只有三种:
1.在单词 A 中插入一个字符;
2.在单词 B 中插入一个字符;
3.修改单词 A 的一个字符。
转化为子问题:
以A = horse,B = ros 作为例子,
1.在单词 A 中插入一个字符:如果我们知道 horse 到 ro 的编辑距离为 a,那么显然 horse 到 ros 的编辑距离不会超过 a + 1。这是因为我们可以在 a 次操作后将 horse 和 ro 变为相同的字符串,只需要额外的 1 次操作,在单词 A 的末尾添加字符 s,就能在 a + 1 次操作后将 horse 和 ro 变为相同的字符串;
2.在单词 B 中插入一个字符:如果我们知道 hors 到 ros 的编辑距离为 b,那么显然 horse 到 ros 的编辑距离不会超过 b + 1,原因同上;
3.修改单词 A 的一个字符:如果我们知道 hors 到 ro 的编辑距离为 c,那么显然 horse 到 ros 的编辑距离不会超过 c + 1,原因同上。
那么,从 horse 变成 ros 的编辑距离应该为 min(a + 1, b + 1, c + 1)。
继续拆分,直到:
1.字符串 A 为空,如从 转换到 ro,显然编辑距离为字符串 B 的长度,这里是 2;
2.字符串 B 为空,如从 horse 转换到 ,显然编辑距离为字符串 A 的长度,这里是 5。
复杂度
时间复杂度 :O(mn),其中 m 为 word1 的长度,n 为 word2 的长度。
空间复杂度 :O(mn),我们需要大小为O(mn) 的 D 数组来记录状态值。
代码
用dp[m][n]表示,长为m的字符串A,和长为n的字符串B,的编辑距离。
class Solution {
public int minDistance(String word1, String word2) {
int m=word1.length();
int n=word2.length();
//都为空串
if(m==0&&n==0)
return 0;
//有一个为空串
if(m==0||n==0)
return m+n;
int[][] dp=new int[m+1][n+1];
dp[0][0]=0;
//字符串B为空,编辑距离就是字符串A长度
for(int i=1;i<=m;i++){
dp[i][0]=i;
}
//字符串A为空,编辑距离就是字符串B长度
for(int i=1;i<=n;i++){
dp[0][i]=i;
}
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
int a=dp[i-1][j];//在A末尾插入一个字符
int b=dp[i][j-1];//在B末尾插入一个字符
int c=dp[i-1][j-1];//
if(word1.charAt(i-1)!=word2.charAt(j-1)){
c+=1;
}
dp[i][j]=Math.min(Math.min(a+1,b+1),c);
}
}
return dp[m][n];
}
}