https://github.com/ztane/python-Levenshtein/
https://pypi.org/project/python-Levenshtein/
Levenshtein.distance(str1,str2)
1.百度百科介紹:
Levenshtein 距離,又稱編輯距離,指的是兩個字符串之間,由一個轉換成另一個所需的最少編輯操作次數。
許可的編輯操作包括將一個字符替換成另一個字符,插入一個字符,刪除一個字符。
編輯距離的算法是首先由俄國科學家Levenshtein提出的,故又叫Levenshtein Distance。
2.用途
模糊查詢
3.實現過程
a.首先是有兩個字符串,這裏寫一個簡單的 abc和abe
b.將字符串想象成下面的結構。
A處 是一個標記,爲了方便講解,不是這個表的內容。
abc | a | b | c | |
abe | 0 | 1 | 2 | 3 |
a | 1 | A處 | ||
b | 2 | |||
e | 3 |
c.來計算A處 出得值
它的值取決於:左邊的1、上邊的1、左上角的0.
按照Levenshtein distance的意思:
上面的值和左面的值都要求加1,這樣得到1+1=2。
A處 由於是兩個a相同,左上角的值加0.這樣得到0+0=0。
這是後有三個值,左邊的計算後爲2,上邊的計算後爲2,左上角的計算爲0,所以A處 取他們裏面最小的0.
d.於是表成爲下面的樣子
abc | a | b | c | |
abe | 0 | 1 | 2 | 3 |
a | 1 | 0 | ||
b | 2 | B處 | ||
e | 3 |
在B處 會同樣得到三個值,左邊計算後爲3,上邊計算後爲1,在B處 由於對應的字符爲a、b,不相等,所以左上角應該在當前值的基礎上加1,這樣得到1+1=2,在(3,1,2)中選出最小的爲B處的值。
e.於是表就更新了
abc | a | b | c | |
abe | 0 | 1 | 2 | 3 |
a | 1 | 0 | ||
b | 2 | 1 | ||
e | 3 | C處 |
C處 計算後:上面的值爲2,左邊的值爲4,左上角的:a和e不相同,所以加1,即2+1,左上角的爲3。
在(2,4,3)中取最小的爲C處 的值。
f.於是依次推得到
a | b | c | ||
0 | 1 | 2 | 3 | |
a | 1 | A處 0 | D處 1 | G處 2 |
b | 2 | B處 1 | E處 0 | H處 1 |
e | 3 | C處 2 | F處 1 | I處 1 |
I處: 表示abc 和abe 有1個需要編輯的操作。這個是需要計算出來的。
同時,也獲得一些額外的信息。
A處: 表示a 和a 需要有0個操作。字符串一樣
B處: 表示ab 和a 需要有1個操作。
C處: 表示abe 和a 需要有2個操作。
D處: 表示a 和ab 需要有1個操作。
E處: 表示ab 和ab 需要有0個操作。字符串一樣
F處: 表示abe 和ab 需要有1個操作。
G處: 表示a 和abc 需要有2個操作。
H處: 表示ab 和abc 需要有1個操作。
I處: 表示abe 和abc 需要有1個操作。
g.計算相似度
先取兩個字符串長度的最大值maxLen,用1-(需要操作數除maxLen),得到相似度。
例如abc 和abe 一個操作,長度爲3,所以相似度爲1-1/3=0.666。
4.代碼實現
package code;
/**
* @className:MyLevenshtein.java
* @classDescription:Levenshtein Distance 算法實現
* 可以使用的地方:DNA分析 拼字檢查 語音辨識 抄襲偵測
* @author:donghai.wan
* @createTime:2012-1-12
*/
public class MyLevenshtein {
public static void main(String[] args) {
//要比較的兩個字符串
String str1 = "今天星期四";
String str2 = "今天是星期五";
levenshtein(str1,str2);
}
/**
* DNA分析 拼字檢查 語音辨識 抄襲偵測
*
* @createTime 2012-1-12
*/
public static void levenshtein(String str1,String str2) {
//計算兩個字符串的長度。
int len1 = str1.length();
int len2 = str2.length();
//建立上面說的數組,比字符長度大一個空間
int[][] dif = new int[len1 + 1][len2 + 1];
//賦初值,步驟B。
for (int a = 0; a <= len1; a++) {
dif[a][0] = a;
}
for (int a = 0; a <= len2; a++) {
dif[0][a] = a;
}
//計算兩個字符是否一樣,計算左上的值
int temp;
for (int i = 1; i <= len1; i++) {
for (int j = 1; j <= len2; j++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
temp = 0;
} else {
temp = 1;
}
//取三個值中最小的
dif[i][j] = min(dif[i - 1][j - 1] + temp, dif[i][j - 1] + 1,
dif[i - 1][j] + 1);
}
}
System.out.println("字符串\""+str1+"\"與\""+str2+"\"的比較");
//取數組右下角的值,同樣不同位置代表不同字符串的比較
System.out.println("差異步驟:"+dif[len1][len2]);
//計算相似度
float similarity =1 - (float) dif[len1][len2] / Math.max(str1.length(), str2.length());
System.out.println("相似度:"+similarity);
}
//得到最小值
private static int min(int... is) {
int min = Integer.MAX_VALUE;
for (int i : is) {
if (min > i) {
min = i;
}
}
return min;
}
}
1. Levenshtein.hamming(str1, str2)
計算漢明距離。要求str1和str2必須長度一致。是描述兩個等長字串之間對應位置上不同字符的個數。如
2. Levenshtein.distance(str1, str2)
計算編輯距離(也成Levenshtein距離)。是描述由一個字串轉化成另一個字串最少的操作次數,在其中的操作包括插入、刪除、替換。如
算法實現 參考動態規劃整理:http://www.cnblogs.com/kaituorensheng/archive/2013/05/15/3080990.html。
3. Levenshtein.ratio(str1, str2)
計算萊文斯坦比。計算公式 r = (sum - ldist) / sum, 其中sum是指str1 和 str2 字串的長度總和,ldist是類編輯距離
注意:這裏的類編輯距離不是2中所說的編輯距離,2中三種操作中每個操作+1,而在此處,刪除、插入依然+1,但是替換+2
這樣設計的目的:ratio('a', 'c'),sum=2,按2中計算爲(2-1)/2 = 0.5,’a','c'沒有重合,顯然不合算,但是替換操作+2,就可以解決這個問題。
4. Levenshtein.jaro(s1, s2)
計算jaro距離,
其中的m爲s1, s2的匹配長度,當某位置的認爲匹配 當該位置字符相同,或者在不超過
t是調換次數的一半
5. Levenshtein.jaro_winkler(s1, s2)
計算Jaro–Winkler距離