【Leetcode】【DP】 72. Edit Distance / 編輯距離
阿新 • • 發佈:2018-11-10
Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.
You have the following 3 operations permitted on a word:
- Insert a character
- Delete a character
- Replace a character
Example 1:
Input: word1 = "horse", word2 = "ros" Output: 3 Explanation: horse -> rorse (replace 'h' with 'r') rorse -> rose (remove 'r') rose -> ros (remove 'e')
Example 2:
Input: word1 = "intention", word2 = "execution" Output: 5 Explanation: intention -> inention (remove 't') inention -> enention (replace 'i' with 'e') enention -> exention (replace 'n' with 'x') exention -> exection (replace 'n' with 'c') exection -> execution (insert 'u')
Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2.
給定兩個字串,求編輯距離。編輯距離即是對字串進行:刪除一個字元,插入一個字元,替換一個字元 的操作,每個操作計數1,從字串1到字串2的運算元即為編輯距離。
可畫圖分析:
如,由字串A:please 和字串B:apple。長度為m和n。
首先構建一個 (m+1) x (n+1) 的二維陣列,定義
dp[i][j] (此處取dp[2][2],即 pl 和 ap )分析如下:
首先之前已經求得了dp [2-1] [2] (p和ap的編輯距離),dp [2] [2-1] (pl和a), dp [2-1] [2-1] (p和a)。
- pl -> ap 可先 ap -> p (等同於p->ap) ,再加上一個 插入l 的操作,即為 dp [1] [2] + 1 ,擴充套件為 dp [i] [j] = dp [i-1] [j] + 1
- pl -> ap 可先 pl -> a ,再加上一個 插入p 的操作,即為 dp [2] [1] + 1 ,擴充套件為 dp [i] [j] = dp [i] [j-1] + 1
- pl -> ap 可先 p -> a ,再加上一個 將 l 換為 p 的操作,即為 dp [1] [1] + 1 ,擴充套件為 dp [i] [j] = dp [i-1] [j-1] + 1。但如果替換操作中的A[2] = B[2], 如 pl -> al 的操作,p -> a ,再加上一個 將 l 換為 l 的操作,即無需操作,dp [1] [1] + 0 ,擴充套件為 dp [i] [j] = dp [i-1] [j-1] + 0。定義這個0/1運算元為cost,if A[i] == B[j] , cost = 0, 否則cost = 1。dp [i] [j] = dp [i-1] [j-1] + cost
綜上,欲得到最小編輯距離,dp = 三種情況的最小值。
故進行以下幾步:
- 構建 (m+1) x (n+1) 的二維陣列
- 初始狀態:第一行(由A空字串到B的編輯距離)/第一行。
- 由dp公式遞推
- 返回最右下值
總公式:
int minDistance(string word1, string word2) {
int m = word1.size();
int n = word2.size();
if(m==0 || n==0)
return m+n;
vector<vector<int>> dp(m+1, vector<int>(n+1, 0));
for(int i=0; i<=n; i++) {
dp[0][i] = i;
}
for(int i=0; i<=m; i++) {
dp[i][0] = i;
}
int cost = 0;
for(int i=1; i<=m; i++) {
for(int j=1; j<=n; j++) {
if(word1[i-1] == word2[j-1]) // 此處檢查word1的當前字元和word2的當前字元是否相等
cost = 0; // 相等則說明,當前段的編輯轉換 等於 從word1的前一段轉換到word2的前一段
else
cost = 1; // 否則需要進行一次轉換操作,即已知A和B的前一段轉換需要x操作,則當前需要再對後面這個字母進行一次替換操作
dp[i][j] = min(dp[i-1][j-1]+cost, min(dp[i-1][j]+1, dp[i][j-1]+1));
}
}
return dp[m][n]; // 矩陣為 m+1 x n+1, 故最終返回dp[m][n]
}
易錯處:
dp初始化時需要先將第一行第一列初始化,因為後續遞推式有 i-1 和 j-1 項。
dp長度時 m+1,n+1的,記住迴圈的邊界在 i<=m,j<=n。以及最後返回值是dp[m][n]
求三項最小值應用兩個min組合來得到