1. 程式人生 > >計算兩個字串相似度的演算法

計算兩個字串相似度的演算法

該方法是使用的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的矩陣儲存距離值。演算法大概過程:

  1. str1或str2的長度為0返回另一個字串的長度。
  2. 初始化(n+1)*(m+1)的矩陣d,並讓第一行和列的值從0開始增長。
  3. 掃描兩字串(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三者的最小值。
  4. 掃描完後,返回矩陣的最後一個值即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;
	}