Python如何計算編輯距離?


算法原理

在計算文本的相似性時,經常會用到編輯距離。編輯距離,又稱Levenshtein距離,是指兩個字串之間,由一個轉成另一個所需的最少編輯操作次數。通常來說,編輯距離越小,兩個文本的相似性越大。這里的編輯操作主要包括三種:

  • 插入:將一個字符插入某個字符串;
  • 刪除:將字符串中的某個字符刪除;
  • 替換:將字符串中的某個字符替換為另外一個字符。

下面通過示例來看一下。

將字符串batyu變為beauty,編輯距離是多少呢?這需要經過如下步驟:

1、batyu變為beatyu(插入字符e)

2、beatyu變為beaty(刪除字符u)

3、beaty變為beauty(插入字符u)

所以編輯距離為3。

那么,如何用Python計算編輯距離呢?我們可以從較為簡單的情況進行分析。

  • 當兩個字符串都為空串,那么編輯距離為0;
  • 當其中一個字符串為空串時,那么編輯距離為另一個非空字符串的長度;
  • 當兩個字符串均為非空時(長度分別為 i 和 j ),取以下三種情況最小值即可:
  • 1、長度分別為 i-1 和 j 的字符串的編輯距離已知,那么加1即可;
  • 2、長度分別為 i 和 j-1 的字符串的編輯距離已知,那么加1即可;
  • 3、長度分別為 i-1 和 j-1 的字符串的編輯距離已知,此時考慮兩種情況,若第i個字符和第j個字符不同,那么加1即可;如果相同,則不需要加1。

很明顯,上述算法的思想即為動態規划

求長度為m和n的字符串的編輯距離,首先定義函數——edit(i, j),它表示第一個長度為i的字符串與第二個長度為j的字符串之間的編輯距離。動態規划表達式可以寫為:

  • if i == 0 且 j == 0,edit(i, j) = 0
  • if (i == 0 且 j > 0 )或者 (i > 0 且j == 0),edit(i, j) = i + j
  • if i ≥ 1 且 j ≥ 1 ,edit(i, j) == min{ edit(i-1, j) + 1, edit(i, j-1) + 1, edit(i-1, j-1) + d(i, j) },當第一個字符串的第i個字符不等於第二個字符串的第j個字符時,d(i, j) = 1;否則,d(i, j) = 0。

最終的編輯距離即為edit(m,n)。上述示例的edit矩陣可以表示如下:

Python代碼實現

Talk is cheap. Show me the code. Python代碼也是極其簡潔的,這也是動態規划的魅力:

擴展

那么,Python功能這么強大,有沒有計算編輯距離的包呢?

答案是肯定的,Python中的Levenshtein包可以用來計算編輯距離,安裝方法很簡單,直接安裝即可:

pip install python-Levenshtein

這樣我們就可以引入包直接計算編輯距離了:

有同學可能想計算漢字之間的編輯距離,如下:

得到的結果是3而不是1。這是因為在字符串編碼為utf-8時,一個漢字占用3個字節。改為unicode編碼即可得到1,即:

那么,Levenshtein包中還有沒有其它計算距離的方法呢?

這個包有很多計算距離的方法,包括如下:

  • hamming(str1, str2),計算長度相等的字符串str1和str2的漢明距離,即為兩個等長字串之間對應位置上不同字符的個數。
  • ratio(str1, str2),計算萊文斯坦比。計算公式 r = (sum – ldist) / sum, 其中sum是指str1 和 str2 字串的長度總和,ldist是類編輯距離。注意這里是類編輯距離,在類編輯距離中刪除、插入依然+1,但是替換+2。
  • jaro(str1, str2),jaro_winkler(str1, str2)等等。

總結

  • 可以用動態規划算法求解字符串的編輯距離。
  • PyPi包Levenshtein可以用來計算字符串的編輯距離,也可以計算其它類型的距離。

轉載:
https://www.jianshu.com/p/9a53f32cf62b


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM