UNIX系統下有一個行編輯器ed,它每次只對一行文本作刪除一個字符、插入一個字符或替換一個字符三種操做。例如某一行的內容是「ABC」,通過把第二個字符替換成「D」、刪除第一個字符、末尾插入一個字符「B」,這三步操做後,內容就變成了「DCB」。即「ABC」變成「DCB」須要通過3步操做,咱們稱它們的編輯距離爲3。
如今給你兩個任意字符串(不包含空格),請幫忙計算它們的最短編輯距離。 java
輸入包含多組數據。每組數據包含兩個字符串m和n,它們僅包含字母,而且長度不超過1024。算法
ABC CBCD ABC DCB
2 3
設A和B是2個字符串。要用最少的字符操做將字符串A轉換爲字符串B。這裏所說的字符操做包括:
(1) 刪除一個字符;
(2) 插入一個字符;
(3) 將一個字符改成另外一個字符。
將字符串A變換爲字符串B所用的最少字符操做數稱爲字符串A到B的編輯距離。設A的長度爲m,B的長度爲n建立一個二維數組d,大小爲(m+1)*(n+1),來記錄a1-am與b1-bn之間的編輯距離,要遞推時,須要考慮對其中一個字符串的刪除操做、插入操做和替換操做分別花費的開銷,從中找出一個最小的開銷即爲所求結果。
操做步驟:
(一) 狀況一:當A的長度爲0,B的長度爲j時,最小編輯距離就是j。
(二) 狀況二:當A的長度爲i,B的長度爲0時,最小編輯距離就是i。
(三) 狀況三:當A的長度爲i,B的長度爲j時,d[i][j]=min{d[i-1][j]+1,d[i][j-1]+1, d[i-1][j-1]+(A[i]==B[j]?0:1)}
其中:
● d[i][j]表示A的前i個字符和B的前j個字符相同後的最短距離。
● d[i][j]來自於三種狀態
■ 刪除,d[i-1][j]+1,A1,…,Ai-1通過操做能夠變成了B1,…,Bj,那麼A1,…,Ai-1Ai變爲B1,…,Bj必定要刪除Ai。
■ 插入,d[i][j-1]+1,A1,…,Ai通過操做能夠變成了B1,…,Bj-1Bj,那麼A1,…,Ai-1Ai變爲B1,…,Bj-1Bj必定要添加一個字符。
■ 替換,若是A[i]=B[j],能夠不進行額外的操做,那麼有d[i][j]=d[i-1][j-1],若是不A[i]≠B[j],那麼就要進行一次替換操做,有d[i][j]=d[i-1][j-1]+1。
注意:此處字符串中字符開始的下標從1開始計算
根據分析能夠獲得遞推方程:
數組
d[i][j]=⎧⎩⎨jimin{d[i−1][j]+1,d[i][j−1]+1,d[i−1][j−1]+f(i,j)}i=0j=0i>0andj>0編輯器
f(i,j)={10i>0andj>0andA[i]≠B[j]i>0andj>0andA[i]=B[j]測試
import java.util.Scanner; /** * Declaration: All Rights Reserved !!! */ public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // Scanner scanner = new Scanner(Main.class.getClassLoader().getResourceAsStream("data.txt")); while (scanner.hasNext()) { String s = scanner.next(); String t = scanner.next(); System.out.println(shortest(s, t)); } scanner.close(); } /** * 最短編輯距離 * * @param s 字符串 * @param t 字符串 * @return 最短編輯距離 */ private static int shortest(String s, String t) { int row = s.length() + 1; int col = t.length() + 1; // 初始化 int[][] d = new int[row][col]; for (int i = 0; i < row; i++) { d[i] = new int[col]; } // 設置第一列 for (int i = 0; i < row; i++) { d[i][0] = i; } // 設置第一行 for (int j = 0; j < col; j++) { d[0][j] = j; } for (int i = 1; i < row; i++) { for (int j = 1; j < col; j++) { int u = d[i - 1][j] + 1; int v = d[i][j - 1] + 1; int w = d[i - 1][j - 1]; if (s.charAt(i - 1) != t.charAt(j - 1)) { w++; } d[i][j] = Math.min(u, Math.min(v, w)); } } return d[row - 1][col - 1]; } }