今天我們來研究乙個有趣的演算法題,叫做字串編輯距離。編輯距離研究的問題和最長公共子串行有相似之處,都是比較兩個字串之間的相似性,只是採用的標準不太相同。
(1)刪除乙個字元(delete);
(2)插入乙個字元(insert);
(3)將乙個字元改為另乙個字元(substitute)。
將字串a變換為字串b所用的最少字元運算元稱為字串a到b的編輯距離(edit distance)。通常情況下,三種操作的代價是一樣的,也即每種字元操作都會導致一次變換,這也符合我們平常的認知。但是,有時也可以對這三種操作施加不同的影響因子,使演算法傾向於某種變換,可以通過修改三種操作的代價來實現。
事實上,也可以包含更多的字元操作。例如,在英文輸入的過程中經常會出現不小心交換兩個字元的問題(trueàture),所以可以增加乙個新的操作—置換(transposition),表示互換相鄰的兩個字元,此時編輯距離公升級為damerau–levenshteindistance距離,它包含插入、刪除、替換和置換四種操作。在ocr應用中還存在其他操作:將兩個字元合併(merge)成乙個或者將乙個字元展開(split)成兩個。當然,也可以減少字元操作,例如求兩個等長字串的漢明距離只用到了替換操作;還有,在求最長公共子串行(lcs)的問題中,其實等價於我們只採用插入和刪除兩種操作,雖然在lcs問題中求的是公共序列,我們也可以求它們之間的簡化版編輯距離。
編輯距離應用很廣,最初的應用是拼寫檢查和近似字串匹配。在生物醫學領域,科學家將dna看成有a,s,g,t構成的字串,然後採用編輯距離判斷不同dna的相似度。關於近似字串匹配,lcs也是乙個不錯的選擇,在不同的問題中都有自己的用武之地。
編輯距離另乙個很好的用途在語音識別中,它被當作乙個評測指標。語音測試集的每一句話都有乙個標準答案,然後利用編輯距離判斷識別結果和標準答案之間的不同。不同的錯誤可以反映識別系統存在的問題。假如識別結果中插入錯誤較多,表示識別結果丟字很多,乙個可能的原因是vad做得不好;又或者識別結果中替換錯誤較多,則很有可能是訓練過程中的語言模型不好。
再看乙個應用,在linux下我們經常會用diff命令或者vimdiff命令按行比較兩個檔案的不同。執行命令之後會展示出兩個檔案的不同,展示方式其實就是按照編輯距離來定義的:哪個位置插入多少行或者刪除多少行或者替換哪幾行。所以我們可以用編輯距離來實現diff命令。
該問題和lcs一樣,也是利用動態規劃來解決。定義dij表示長度為i的字串a變為長度為j的字串b需要的編輯距離。需要注意的一點是,如果字串a的最終長度為m,字串b的最終長度為n,則d矩陣是乙個(m+1)*(n+1)的矩陣,因為它可以表示長度為0的字串之間的轉換。它的遞推式滿足:
我們解釋一下上面的公式,前兩行是初始化,分別表示字串b和a為空時對應的編輯距離計算。當字串b為空時,我們將a變為b只需要不停地刪除字元即可,反之則不停地新增字元。初始化完矩陣d的最初一行和一列之後我們就可以按照第三行公式去計算矩陣的剩餘元素。第(i,j)個元素在計算的時候依賴於和它相鄰的三個位置 (i-1,j-1)、(i,j-1)和(i-1,j)。公式的整體結構和lcs,dtw都非常像,唯一存在的難點就是到底哪乙個位置對應刪除操作,哪乙個位置對應插入操作。由公式可以看出,(i-1,j)對應刪除操作,(i,j-1)對應插入操作。可以這樣理解,現在耗費了di-1,j步操作將字串a(1,i-1)轉換成了b(1,j),則在將a(1,i)轉換成b(1,j)時,我們可以直接刪掉字元a(i),問題變成a(1,i-1)轉換成b(1,j),從而dij就等於di-1,j+1。同理,現在耗費了di,j-1步操作將字串a(1,i)轉換成了b(1,j-1),則在將a(1,i)轉換成b(1,j)時,我們可以將b(j)新增到a(1,i)末尾(此時a(1,i)已轉換成b(1,j-1))構成b(1,j)。
事實上,對damerau–levenshteindistance距離的擴充套件在明白了基礎的編輯距離之後也非常簡單,無非是增加了一種置換操作而已,遞推式如下:
編輯距離及編輯距離演算法
編輯距離概念描述 編輯距離,又稱levenshtein距離,是指兩個字串之間,由乙個轉成另乙個所需的最少編輯操作次數。許可的編輯操作包括將乙個字元替換成另乙個字元,插入乙個字元,刪除乙個字元。例如將kitten一字轉成sitting sitten k s sittin e i sitting g 俄...
編輯距離及編輯距離演算法
include include include using namespace std const int max 1001 int maxlen max max int maxlen string str1,string str2 return maxlen len1 len2 int main ...
編輯距離及編輯距離演算法
include include include using namespace std const int max 1001 int maxlen max max int maxlen string str1,string str2 return maxlen len1 len2 int main ...