编辑距离
动态规划——困难
给定两个单词word1和word2,请计算将word1转换为word2至少需要多少步操作。
你可以对一个单词执行以下3种操作:
a)在单词中插入一个字符
b)删除单词中的一个字符
c)替换单词中的一个字符
动态规划
问题:
单词1 转换为 单词2 最少需要操作几次?(插入,或删除,替换)
状态分析:
子问题:单词1的前j个字符 转换为 单词2 的前i个字符,最少需要操作几次?
dp(j,i) :单词1的前j个字符 转换为 单词2 的前i个字符,最少需要操作的次数
状态转移方程:
dp(j,i) = min(dp(j-1,i) +1, dp(j,i-1)+1,dp(i-1,j-1)+{s1[j] == s2[i]?0:1})
j < i : dp(j,j) +i-j;
j==i: dp(j-1,i-1)+{s1[j] == s2[i]?0:1};
j > i: dp( i , i )+j-i;
F(i-1,j): w1[1,…,i-1]于w2[1,…,j]的编辑距离,删除w1[i]的字符—>F(i,j)
F(i,j-1): w1[1,…,i]于w2[1,…,j-1]的编辑距离,增加一个字符—>F(i,j)
F(i-1,j-1): w1[1,…,i-1]于w2[1,…,j-1]的编辑距离,如果w1[i]与w2[j]相同,
不做任何操作,编辑距离不变,如果w1[i]与w2[j]不同,替换w1[i]的字符为w2[j]—>F(i,j)初始值:
j == 0: dp(0,i) = i;
i == 0: dp(j,0) = j;
返回值:
dp(s1.length,s2.length);
public int minDistance (String word1, String word2) {
// write code here
int n = word1.length();
int m = word2.length();
if(word1.isEmpty() || word2.isEmpty())
return Math.max(n,m);
int[][] dp = new int[n+1][m+1];
//初始化
for(int i=0;i<=n;i++){
dp[i][0] = i;
}
for(int i=0;i<=m;i++){
dp[0][i] = i;
}
//状态
for(int j = 1;j<=n;j++){
for(int i = 1;i<=m;i++){
int count = word1.charAt(j-1)==word2.charAt(i-1)?0:1;
int replace = dp[j-1][i-1] + count;
dp[j][i] = Math.min(dp[j-1][i],dp[j][i-1])+1;
dp[j][i] = Math.min(dp[j][i],replace);
}
}
return dp[n][m];
}
注:字符串类的动态规划,可引入空串进行初始化
动规一点也不难!!!?