1.問題定義
編輯距離又稱爲Levenshtein距離,是指兩個字符串之間,從一個字符串變成另一個字符串所需要的最小編輯操作次數。可以採用的編輯操作包括:插入操作、替換操作和刪除操作。例如:字符串“a“ 與字符串 ”b“的編輯距離爲1,只有一個替換操作。
將”kitten一字轉成“sitting”的編輯距離爲3:
sitten (k→s):替換操作
sittin (e→i):替換操作
sitting (→g):插入操作
2.問題分析
編輯距離問題可以採用動態規劃的方式來解決。假設dp[i][j]表示字符串的長度爲i的字符串strA[0...i-1]和字符串長度爲j的字符串strB[0...j-1]的編輯距離。接下來就要分析dp[i][j]與dp[i-1][j-1]、dp[i-1][j]、dp[i][j-1]之間的關係。
假設strA的最後一個字符爲‘x’,strB的最後一個字符爲‘y’,則通過‘x’與‘y’的關係得到如下:
1)如果x==y,則dp[i][j]=dp[i-1][j-1];
2)如果x!=y,將x替換爲y,則dp[i][j]=dp[i-1][j-1]+1;
3)如果x!=y,將y插入到x後面,則dp[i][j]=dp[i][j-1]+1;
4)如果x!=y,將x從strA中刪除,則dp[i][j]=dp[i-1][j]+1;
在x!=y的情況下,dp[i][i]的值爲2)3)4)中的最小值。
初始條件:
dp[i][0]=i,dp[0][j]=j.
3.程序實現
public class EditDistance { /** * @author Qunzer * @since 2013/12/16 */ public static void main(String[] args) { // TODO Auto-generated method stub String strA = "hello"; String strB = "helli1"; System.out.println("Edit distance is :" + getEditDistance(strA, strB)); } // 求解編輯距離的靜態方法 public static int getEditDistance(String strA, String strB) { int lenA = strA.length(); int lenB = strB.length(); int[][] dp = new int[lenA + 1][lenB + 1]; int i, j; for (i = 0; i < lenA; i++) { dp[i][0] = i; } for (j = 0; j < lenB; ++j) { dp[0][j] = j; } for (i = 0; i < lenA; ++i) { char c1 = strA.charAt(i); for (j = 0; j < lenB; ++j) { char c2 = strB.charAt(j); if (c1 == c2) dp[i + 1][j + 1] = dp[i][j]; else { int replaceTemp = dp[i][j] + 1; int insertTemp = dp[i + 1][j] + 1; int deleteTemp = dp[i][j + 1] + 1; dp[i + 1][j + 1] = getMin(replaceTemp, insertTemp, deleteTemp); } } } return dp[lenA][lenB]; } // 得到三個中的最小值 public static int getMin(int a, int b, int c) { int min = a > b ? b : a; return (c > min ? min : c); } }
4.輯距離的應用
編輯距離可以用到以下場景:
DNA分析
拼字檢查
語音辨識
抄襲偵測
相似度計算