【问题】给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:
插入一个字符
删除一个字符
替换一个字符

示例 1:

输入: word1 = "horse", word2 = "ros"
输出: 3
解释: 
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')

【思路】

利用动态规划的思想,我们可以得到以下几个递推式:
在DP矩阵初始化时,dp[i][j]表示source[0:i]编辑成result[0:j]所需要的最小编辑距离,因此当i=0或者j=0,则需要最小编辑距离为非零长度字符串的长度(依次插入或删除)。

  1. 如果source[i]和result[j]字母相同,则cost[i][j] = cost[i-1][j-1],相同字符不进行处理,不需要操作数。

  2. 将对word1处理转换为word1和word2的处理:

     

  • word1 插入一个字符 dp[i-1][j] + 1 -> dp[i][j]

  • word1 删除一个字符 = word2 插入一个字符 dp[i][j-1] + 1 -> dp[i][j]

  • word1 替换一个字符 = word1 word2 都替换一个字符 dp[i-1][j-1] + 1 -> dp[i][j]

综上所述,其状态方程可以总结为两个:
当word1[i] == word2[j],则dp[i][j] = dp[i-1][j-1], 即没有操作
当word1[i] != word2[j],则dp[i][j] = 1 + min(cost[i-1][j-1], min(cost[i][j-1], cost[i-1][j])),每步最小的操作数+1。

class Solution {
public:
    int minDistance(string word1, string word2) {
        int m = word1.length();
        int n = word2.length();

        vector<vector<int>> cost(m+1, vector<int>(n+1));

        for(int i = 0; i <= m; ++i){
            cost[i][0] = i;
        }
        for (int j = 0; j <= n; ++j) {
            cost[0][j] = j;
        }
        for (int i = 1; i <= m; ++i) {
            for (int j = 1; j <= n; ++j) {
                if (word1[i-1] == word2[j-1]) {
                    cost[i][j] = cost[i-1][j-1];
                } else {
                    cost[i][j] = 1 + min(cost[i-1][j-1], min(cost[i][j-1], cost[i-1][j]));
                }             
            }
        }
        return cost[m][n];
    }
};