題目大意
編輯距離,經典動態規劃題目。給出針對字符串的三種操作,替換,刪除和插入,編輯距離d
,表示將字符串a
使用上述三種操作轉換爲b
所需要的步驟。
思路
計算字符串a
和b
之間的編輯距離d
。
-
子問題構造:
a
的前綴子串和b
的前綴子串之間的編輯距離,前綴子串即包含某位置前的所有字符的子串。因爲計算a
的前綴子串與b
的編輯距離時需要考慮b
中的所有字符,因此a
和b
的子串都要考慮。 -
遞推公式: 遞推式需要考慮
a[i]
和b[j]
是否相同的情況,例如對於hoe
和rose
,因爲兩者最後的字符相同,因此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];
}
};
總結
經典題目