編輯距離

編輯距離是指兩個子串之間,由一個轉成另一個所需要的最少編輯操作次數。允許的編輯操作包括:

  • 將一個字符替換成另一個字符

  • 插入一個字符

  • 刪除一個字符

這是常見的求兩個字符編輯距離的題目描述,被稱爲萊文斯坦距離,又稱爲Levenshtein距離,是俄羅斯科學家萊溫斯坦在1965年提出來的概念。 – 來自於維基百科

定義
假設兩個字符串分別爲A,B,長度分別爲n=An=\left| A \right|m=Bm=\left| B \right|,那麼它們的萊文斯坦距離爲levA,B(n,m)lev_{A,B} \left(n, m \right)。公式定義爲:
levA,B(i,j)={max(i,j)if  min(i,j)=0min{levA,B(i1,j)+1levA,B(i,j1)+1levA,B(i1,j1)+IAiBjothersize lev_{A,B} \left(i, j \right) = \left\{\begin{matrix} max \left( i, j \right) & if \; min\left( i, j \right)=0 \\ min \left\{\begin{matrix} lev_{A,B} \left( i -1 , j \right) + 1 \\ lev_{A,B} \left( i , j -1 \right) + 1 \\ lev_{A,B} \left( i -1 , j - 1 \right) + I_{A_{i} \neq B_{j}} \end{matrix}\right. & othersize \end{matrix}\right.
其中lev_{A,B} \left(i, j \right)表示的字符串A的前i個字符與字符串B的前j個字符之間的萊文斯坦距離;
levA,B(i1,j)lev_{A,B} \left( i - 1, j \right) 表示刪除字符
levA,B(i,j1)lev_{A,B} \left( i, j - 1 \right) 表示插入字符
levA,B(i1,j1)lev_{A,B} \left( i -1 , j - 1 \right) 表示字符替換
$ I_{A_{i} \neq B_{j}}是指示函數,A_{i} B_{j}$相等時,取值爲0,否則,取值爲1。

上述是數學描述,真正代碼實現時,由上述的公式可以很清晰地列出動態規劃方程。假設字符串A=horseA=“horse”n=5n=5;字符串B=rosB=“ros”。設編輯數組爲dp,數據初始化如下表形式。

A/B 0 1 2 3
0 0 1 2 3
1 1
2 2
3 3
4 4
5 5

表示的是一個空字符串與字符串AA或字符串BB子串之間的編輯距離。

初始化之後,就需要計算字符串AA中第ii個字符AiA_{i}與字符串B中第jj個字符BjB_{j}的編輯距離了。比較AiA_{i}BjB_{j}

  • 如果AiA_{i}BjB_{j}相等,那麼dp[i][j]=dp[i1][j1]dp[i][j] = dp[i-1][j-1],無需任何操作;

  • 如果AiA_{i}BjB_{j}不相等,那麼就要比較三種操作(刪除,插入和替換)哪一種更優惠,那麼用公式表示就是:dp[i][j]=1+min(dp[i1][j],dp[i][j1],dp[i1][j1])dp[i][j] = 1 + min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])

計算完之後,我們所給的例子字符串A=horseA=“horse”B=rosB=“ros”最後生成的dp數組如下表所示,我們將操作所在的位置加粗顯示。dp[5][3]=3dp[5][3] = 3,字符串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];
    }
};
發佈了56 篇原創文章 · 獲贊 120 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章