編輯距離是指兩個子串之間,由一個轉成另一個所需要的最少編輯操作次數。允許的編輯操作包括:
-
將一個字符替換成另一個字符
-
插入一個字符
-
刪除一個字符
這是常見的求兩個字符編輯距離的題目描述,被稱爲萊文斯坦距離,又稱爲Levenshtein距離,是俄羅斯科學家萊溫斯坦在1965年提出來的概念。 – 來自於維基百科
定義
假設兩個字符串分別爲A,B,長度分別爲和,那麼它們的萊文斯坦距離爲。公式定義爲:
其中lev_{A,B} \left(i, j \right)表示的字符串A的前i個字符與字符串B的前j個字符之間的萊文斯坦距離;
表示刪除字符
表示插入字符
表示字符替換
$ I_{A_{i} \neq B_{j}}A_{i} B_{j}$相等時,取值爲0,否則,取值爲1。
上述是數學描述,真正代碼實現時,由上述的公式可以很清晰地列出動態規劃方程。假設字符串,;字符串。設編輯數組爲dp,數據初始化如下表形式。
A/B | 0 | 1 | 2 | 3 |
---|---|---|---|---|
0 | 0 | 1 | 2 | 3 |
1 | 1 | |||
2 | 2 | |||
3 | 3 | |||
4 | 4 | |||
5 | 5 |
表示的是一個空字符串與字符串或字符串子串之間的編輯距離。
初始化之後,就需要計算字符串中第個字符與字符串B中第個字符的編輯距離了。比較 與 :
-
如果 與 相等,那麼,無需任何操作;
-
如果 與 不相等,那麼就要比較三種操作(刪除,插入和替換)哪一種更優惠,那麼用公式表示就是:。
計算完之後,我們所給的例子字符串和最後生成的dp數組如下表所示,我們將操作所在的位置加粗顯示。,字符串A向B至少需要三步,分別是:第一步:horse -> rorse (將 ‘h’ 替換爲 ‘r’);第二步:rorse -> rose (刪除 ‘r’);第三步:rose -> ros (刪除 ‘e’)。
A/B | 0 | 1 | 2 | 3 |
---|---|---|---|---|
0 | 0 | 1 | 2 | 3 |
1 | 1 | 1 | 2 | 3 |
2 | 2 | 2 | 1 | 2 |
3 | 3 | 2 | 2 | 2 |
4 | 4 | 3 | 3 | 2 |
5 | 5 | 4 | 4 | 3 |
class Solution {
public:
int minDistance(string word1, string word2) {
int len_1 = word1.length();
int len_2 = word2.length();
vector<vector<int>> dp(len_1+1, vector<int>(len_2+1, 0));
for(int i=0;i<len_1+1;i++){
dp[i][0] = i;
}
for(int j=0;j<len_2+1;j++){
dp[0][j] = j;
}
for(int i=0;i<len_1;i++){
for(int j=0;j<len_2;j++){
if(word1[i] == word2[j]){
dp[i+1][j+1] = dp[i][j];
}else{
int min_tmp = dp[i][j+1] < dp[i+1][j] ? dp[i][j+1] : dp[i+1][j];
min_tmp = min_tmp < dp[i][j] ? min_tmp : dp[i][j];
dp[i+1][j+1] = min_tmp + 1;
}
}
}
return dp[len_1][len_2];
}
};