1. 程式人生 > >最短編輯距離(Edit Distance)【DP】

最短編輯距離(Edit Distance)【DP】

概念

編輯距離(最短編輯距離,Edit Distance)又稱Levenshtein
Distance,“是指兩個字串之間,由一個轉成另一個所需的最少編輯操作次數。許可的編輯操作包括將一個字元替換成另一個字元,插入一個字元,刪除一個字元。一般來說,編輯距離越小,兩個串的相似度越大。”
——引用自百度

分析

  • 假設用f[i][j]表示將串a[1…i]轉換為串b[1…j]所需的最少操作次數(最短距離)
  • 首先是邊界:
    ①i==0時,即a為空,那麼對應的f[0][j]的值就為j:增加j個字元,使a轉化為b
    ②j==0時,即b為空,那麼對應的f[i][0]的值就為i:減少i個字元,使a轉化為b

  • 然後考慮一般情況(這裡是DP思想):我們要得到將a[1..i]經過最少次數的操作就轉化為b[1..j],那麼我們就必須在此之前以最少次數(假設為k次)的操作,使現在的a和b只需再做一次操作或者不做操作就可以使a[1..i]轉化到b[1..j]。而“之前”有三種情況:
    ①將a[1…i]轉化為b[1…j-1]
    ②將a[1..i-1]轉化為b[1..j]
    ③將a[1…i-1]轉化為b[1…j-1]

    第①種情況,只需要在最後將a[j]加上b[1..i]就可以了,總共就需要k+1次操作。
    第②種情況,只需要在最後將a[i]刪除,總共需要k+1個操作。
    第③種情況,只需要在最後將a[i]替換為b[j],總共需要k+1個操作。但如果a[i]剛好等於b[j],就不用再替換了,那就只需要k個操作。

  • 為了得到最小值,將以上三種情況的最小值作為f[i][j]的值(我前面不是說了f[i][j]表示串a[1…i]轉換為串b[1…j]所需的最少操作次數嘛),最後答案在f[n][m]中。
  • -

實現(只描述演算法部分)

  1. 初始化。邊界情況,用迴圈巢狀或兩個獨立的迴圈都可以做到。
    初始化長這個樣子
    2.迴圈巢狀遍歷f陣列,先處理a[i]==b[j]的情況,如不滿足,再從三種情況中選擇最小的,作為f[i][j]的值。三種情況中,①如果在k個操作裡將a[1…i-1]轉換為b[1..j],那就可以將a[i]刪除,共需k+1個操作,所以是f[i-1][j]+1;②如果在k個操作裡將a[1…i]轉換為b[1…j-1] ,那就可以加上b[j],共需k+1個操作;③如果我們可以在k個操作裡將a[1…i-1]轉換為b[1…j-1],那就可以將a[i]轉換為b[j],也是共需k+1個操作。(前面已經處理過了a[i]==b[j]的情況)
    3.最後的答案是f[][]最後一個元素的值。

圖解

我們拿POJ的一個樣例來舉例。
剛開始是這樣的:

現在來填表,填表規則:比較a[i-1]和b[j-1]的值(-1是因為字元陣列是從0開始的,而f[][]是從0初始化的,從1開始填,比如說第一個空是f[1][1],卻要比較a[0][0]。),如果相等,其值為其上、左上、左三個元素中的最小值;如果不等,則是三個元素中的最小值+1(如果你懂了填表規則,能填了,說明你已經懂了)
過程如下: