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];
    }
};

總結

經典題目

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