編輯距離即從一個字符串變換到另一個字符串所需要的最少變化操作步驟(以字符為單位,如son到sun,s不用變,將o->s,n不用變,故操作步驟為1)。
為了得到編輯距離,我們畫一張二維表來理解,以beauty和batyu為例:
圖示如1單元格位置即是兩個單詞的第一個字符[b]比較得到的值,其值由它上方的值(1)、它左方的值(1)和、它左上角的值(0)來決定。當單元格所在的行和列所對應的字符(如3對應的是a和b)相等時,它左上角的值+0,否則加1(如在1處,[b]=[b]故左上角的值加0即0+0=0,而在2處[b]!=[b] 故左上角的值加1即1+1=2)。然后再將單元格的左單元格和上單元格的值分別加1,(,然后取相加后得到的三個結果的最小值作為該單元的值如1處相加后其左上、左、上的值為(0,2,2),故1單元格的值為0,而在3處,得到的值為(2,3,1),故3單元格的值為1)。
算法證明
這個算法計算的是將s[1…i]轉換為t[1…j](例如將beauty轉換為batyu)所需最少的操作數(也就是所謂的編輯距離),這個操作數被保存在d[i,j](d代表的就是上圖所示的二維數組)中。
- 在第一行與第一列肯定是正確的,這也很好理解,例如我們將beauty轉換為空字符串,我們需要進行的操作數為beauty的長度(所進行的操作為將beauty所有的字符丟棄)。
- 我們對字符可能進行的操作有三種:
- 將s[1…n]轉換為t[1…m]當然需要將所有的s轉換為所有的t,所以,d[n,m](表格的右下角)就是我們所需的結果。
- 如果我們可以使用k個操作數把s[1…i]轉換為t[1…j-1],我們只需要把t[j]加在最后面就能將s[1…i]轉換為t[1…j],操作數為k+1
- 如果我們可以使用k個操作數把s[1…i-1]轉換為t[1…j],我們只需要把s[i]從最后刪除就可以完成轉換,操作數為k+1
- 如果我們可以使用k個操作數把s[1…i-1]轉換為t[1…j-1],我們只需要在需要的情況下(s[i] != t[j])把s[i]替換為t[j],所需的操作數為k+cost(cost代表是否需要轉換,如果s[i]==t[j],則cost為0,否則為1)。
這個證明過程只能證明我們可以得到結果,但並沒有證明結果是最小的(即我們得到的是最少的轉換步驟)。所以我們引進了另外一個算法,即d[i,j]保存的是上述三種操作中操作數最小的一種。這就保證了我們獲得的結果是最小的操作數
可能進行的改進
- 現在的算法復雜度為O(mn),可以將其改進為O(m)。因為這個算法只需要上一行和當前行被存儲下來就可以了。
- 如果需要重現轉換步驟,我們可以把每一步的位置和所進行的操作保存下來,進行重現。
- 如果我們只需要比較轉換步驟是否小於一個特定常數k,那么只計算高寬寬為2k+1的矩形就可以了,這樣的話,算法復雜度可簡化為O(kl),l代表參加對比的最短string的長度。
- 我們可以對三種操作(添加,刪除,替換)給予不同的權值(當前算法均假設為1,我們可以設添加為1,刪除為0,替換為2之類的),來細化我們的對比。
- 如果我們將第一行的所有cell初始化為0,則此算法可以用作模糊字符查詢。我們可以得到最匹配此字符串的字符串的最后一個字符的位置(index number),如果我們需要此字符串的起始位置,我們則需要存儲各個操作的步驟,然后通過算法計算出字符串的起始位置。
- 這個算法不支持並行計算,在處理超大字符串的時候會無法利用到並行計算的好處。但我們也可以並行的計算cost values(兩個相同位置的字符是否相等),然后通過此算法來進行整體計算。
- 如果只檢查對角線而不是檢查整行,並且使用延遲驗證(lazy evaluation),此算法的時間復雜度可優化為O(m(1+d))(d代表結果)。這在兩個字符串非常相似的情況下可以使對比速度速度大為增加。