最短編輯距離

題目描述

  

1.1 輸入描述:

  UNIX系統下有一個行編輯器ed,它每次只對一行文本作刪除一個字符、插入一個字符或替換一個字符三種操做。例如某一行的內容是「ABC」,通過把第二個字符替換成「D」、刪除第一個字符、末尾插入一個字符「B」,這三步操做後,內容就變成了「DCB」。即「ABC」變成「DCB」須要通過3步操做,咱們稱它們的編輯距離爲3。 
  如今給你兩個任意字符串(不包含空格),請幫忙計算它們的最短編輯距離。 java

1.2 輸出描述:

  輸入包含多組數據。每組數據包含兩個字符串m和n,它們僅包含字母,而且長度不超過1024。算法

1.3 輸入例子:

ABC CBCD
ABC DCB
  •  

1.4 輸出例子:

2
3
  •  

2 解題思路

  設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]測試

 

3 算法實現

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];
    }
}
  •  

4 測試結果

這裏寫圖片描述

相關文章
相關標籤/搜索