LeetCode Daily challenge - Edit Distance 编辑距离

题目大意

编辑距离,经典动态规划题目。给出针对字符串的三种操作,替换删除插入,编辑距离d,表示将字符串a使用上述三种操作转换为b所需要的步骤。

思路

计算字符串ab之间的编辑距离d

  • 子问题构造: a的前缀子串和b的前缀子串之间的编辑距离,前缀子串即包含某位置前的所有字符的子串。因为计算a的前缀子串与b的编辑距离时需要考虑b中的所有字符,因此ab的子串都要考虑。

  • 递推公式: 递推式需要考虑a[i]b[j]是否相同的情况,例如对于hoerose,因为两者最后的字符相同,因此 dis(ho, ros) == dis(hoe, rose) 的距离。

    a[i] == b[j]
         dp[i][j] = min(
             dp[i - 1][j - 1],      // no need replace
             dp[i - 1][j] + 1,     // delete a[i]
             dp[i][j - 1] + 1     // insert b[j]
         )
    a[i] == b[j]
         dp[i][j] = min(
             dp[i - 1][j - 1] + 1,  // replace
             dp[i - 1][j] + 1,     // delete a[i]
             dp[i][j - 1] + 1     // insert b[j]
         )
    

实际上若a[i]==b[j],那么可以肯定dp[i][j]=dp[i-1][j-1]。对了,不要忘了初始化。

代码

typedef vector<vector<int>> vvi;
class Solution {
public:
    int minDistance(string word1, string word2) {
        const int asz = word1.size(), bsz = word2.size();
        if (asz == 0 || bsz == 0) 
            return asz + bsz;

        vvi dp(asz + 1);
        for (size_t i = 0; i <= asz; i++) { 
            dp[i].resize(bsz + 1, max(asz, bsz));
            dp[i][0] = i;
        }

        for (size_t i = 0; i <= bsz; i++) 
            dp[0][i] = i;
        for (size_t dpi = 1; dpi <= asz; dpi++) {
            for (size_t dpj = 1; dpj <= bsz; dpj++) {
                size_t i = dpi - 1, j = dpj - 1;
                if (word1[i] == word2[j]) dp[dpi][dpj] = min({
                        dp[dpi][dpj], dp[dpi - 1][dpj - 1], 
                        dp[dpi - 1][dpj] + 1, dp[dpi][dpj - 1] + 1
                    });
                else dp[dpi][dpj] = min({
                        dp[dpi][dpj], dp[dpi - 1][dpj - 1] + 1,
                        dp[dpi - 1][dpj] + 1, dp[dpi][dpj - 1] + 1
                    });
            }
        }
        return dp[asz][bsz];
    }
};

总结

经典题目

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章