計算兩個字串相似度的演算法
阿新 • • 發佈:2019-02-05
該方法是使用的Levenshtein演算法的一個實現。
簡單介紹下Levenshtein Distance(LD):LD 可能衡量兩字串的相似性。它們的距離就是一個字串轉換成那一個字串過程中的新增、刪除、修改數值。
舉例:
- 如果str1="test",str2="test",那麼LD(str1,str2) = 0。沒有經過轉換。
- 如果str1="test",str2="tent",那麼LD(str1,str2) = 1。str1的"s"轉換"n",轉換了一個字元,所以是1。
如果它們的距離越大,說明它們越是不同。
Levenshtein distance最先是由俄國科學家Vladimir Levenshtein在1965年發明,用他的名字命名。不會拼讀,可以叫它edit distance(編輯距離)。
Levenshtein distance可以用來:
- Spell checking(拼寫檢查)
- Speech recognition(語句識別)
- DNA analysis(DNA分析)
- Plagiarism detection(抄襲檢測)
LD用m*n的矩陣儲存距離值。演算法大概過程:
- str1或str2的長度為0返回另一個字串的長度。
- 初始化(n+1)*(m+1)的矩陣d,並讓第一行和列的值從0開始增長。
- 掃描兩字串(n*m級的),如果:str1[i] == str2[j],用temp記錄它,為0。否則temp記為1。然後在矩陣d[i][j]賦於d[i-1][j]+1 、d[i][j-1]+1、d[i-1][j-1]+temp三者的最小值。
- 掃描完後,返回矩陣的最後一個值即d[n][m]
最後返回的是它們的距離。怎麼根據這個距離求出相似度呢?因為它們的最大距離就是兩字串長度的最大值。對字串不是很敏感。現我把相似度計算公式定為1-它們的距離/字串長度最大值。
public static float similarity(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); } } return 1 - (float) dif[len1][len2] / Math.max(str1.length(), str2.length()); } //得到最小值 public static int min(int... is) { int min = Integer.MAX_VALUE; for (int i : is) { if (min > i) { min = i; } } return min; }