算法设计与分析 3-5 编辑距离问题

3-5 编辑距离问题


问题描述

设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括:
(1)删除一个字符;
(2)插入一个字符;
(3)将一个字符改为另一个字符。

将字符串A变换为字符串B所用的最少字符操作数称为字符串A到B的编辑距离,记为d(A,B)。试设计一个有效算法,对任给的2个字符串A和B,计算出它们的编辑距离d(A,B)。

输入:第1行是字符串A,第2行是字符串B。
输出:字符串A和B的编辑距离d(A,B)


分析

设所给的2个字符串为A[1…m]和B[1…n]。定义D[i, j]= δ (A[1…i], B[1…j])。单字符a,b间的距离定义为
δ (a, b) = 0 当a = b;
δ (a, b) = 1 当a != b;
考察从字符串A[1…i]到字符串B[1…j]的变换。可分以下几种情况来讨论。

  1. 字符A[i]改为字符B[j];需要 δ (A[i], B[j])次操作。
  2. 删除字符A[i];需要1次操作。
  3. 插入字符B[j];需要1次操作。

因此,D[i, j]可递归地计算如下:
D[i, j] = min{ D[i-1, j-1]+ δ (A[i], B[j]), D[i-1, j]+1, D[i, j-1]+1}

D[i, j]的初始值为:
D[i, 0] = i, 0<=i<=m
D[0, j] = j, 0<=j<=n


Java: version 1

import java.util.Scanner;

public class BianJiJuLi {

    public static void main(String[] args){
        String A, B;
        int lenA, lenB;
        char[] tmpA, tmpB;
        char[] arrA, arrB;
        int[][] D;
        int i, j;
        int MAX = 100000;
        int delta;
        Scanner input = new Scanner(System.in);

        while (true){
            A = input.next();//fxpimu
            B = input.next();//xwrs

            lenA = A.length();
            lenB = B.length();
            D = new int[lenA+1][lenB+1];

            tmpA = A.toCharArray();
            tmpB = B.toCharArray();

            arrA = new char[lenA+1];
            arrB = new char[lenB+1];

            System.arraycopy(tmpA, 0, arrA, 1, lenA);
            System.arraycopy(tmpB, 0, arrB, 1, lenB);

            for(i=1; i<=lenA; i++)
                D[i][0] = i;

            for(j=1; j<=lenB; j++)
                D[0][j] = j;

            for(i=1; i<=lenA; i++)
                for(j=1; j<=lenB; j++){
                    D[i][j] = MAX;
                    if(arrA[i] == arrB[j])
                        delta = 0;
                    else
                        delta = 1;
                    if(D[i][j] > D[i-1][j-1]+delta)
                        D[i][j] = D[i-1][j-1]+delta;
                    if(D[i][j] > D[i-1][j]+1)
                        D[i][j] = D[i-1][j]+1;
                    if(D[i][j] > D[i][j-1]+1)
                        D[i][j] = D[i][j-1]+1;
                }

             System.out.println(D[lenA][lenB]);
        }
    }
}

import java.util.Scanner;

public class BianJiJuLi {

    public static void main(String[] args){
        String A, B;
        int lenA, lenB;
        char[] tmpA, tmpB;
//        char[] arrA, arrB;
        int[][] D;
        int i, j;
        int MAX = 100000;
        int delta;
        Scanner input = new Scanner(System.in);

        while (true){
            A = input.next();//fxpimu
            B = input.next();//xwrs

            lenA = A.length();
            lenB = B.length();
            D = new int[lenA+1][lenB+1];

            tmpA = A.toCharArray();
            tmpB = B.toCharArray();

//            arrA = new char[lenA+1];
//            arrB = new char[lenB+1];

//            System.arraycopy(tmpA, 0, arrA, 1, lenA);
//            System.arraycopy(tmpB, 0, arrB, 1, lenB);

            for(i=1; i<=lenA; i++)
                D[i][0] = i;

            for(j=1; j<=lenB; j++)
                D[0][j] = j;

            for(i=1; i<=lenA; i++)
                for(j=1; j<=lenB; j++){
                    D[i][j] = MAX;
                    if(tmpA[i-1] == tmpB[j-1])
//                    if(arrA[i] == arrB[j])
                        delta = 0;
                    else
                        delta = 1;
                    if(D[i][j] > D[i-1][j-1]+delta)
                        D[i][j] = D[i-1][j-1]+delta;
                    if(D[i][j] > D[i-1][j]+1)
                        D[i][j] = D[i-1][j]+1;
                    if(D[i][j] > D[i][j-1]+1)
                        D[i][j] = D[i][j-1]+1;
                }

             System.out.println(D[lenA][lenB]);
        }
    }
}

Input & Output

fxpimu
xwrs
5

fxpimu
fxpimu
0

fxpimu
f
5

fxpimu
mu
4

fxpimu
u
5

fxpimu
q
6

Java: version 2

import java.util.Scanner;

public class BianJiJuLi1 {

    public static void main(String[] args){
        String A, B;
        int lenA, lenB;
        char[] arrA, arrB;
        int[] D;
        int i, j;
        int MAX = 100000;
        int delta;
        int x, y, z;
        Scanner input = new Scanner(System.in);

        while (true){
            A = input.next();//fxpimu
            B = input.next();//xwrs

            lenA = A.length();
            lenB = B.length();
            D = new int[lenB+1];

            arrA = A.toCharArray();
            arrB = B.toCharArray();

            for(j=1; j<=lenB; j++)
                D[j] = j;

            for(i=1; i<=lenA; i++){
                y = i-1;
                for(j=1; j<=lenB; j++){
                    x = y;
                    y = D[j];
                    D[j] = MAX;
                    z = j>1?D[j-1]:i;
                    if(arrA[i-1] == arrB[j-1])
                        delta = 0;
                    else
                        delta = 1;
                    if(D[j] > (x+delta))
                        D[j] = x+delta;
                    if(D[j] > (y+1))
                        D[j] = y+1;
                    if(D[j] > z+1)
                        D[j] = z+1;
                }
            }

            System.out.println(D[lenB]);
        }
    }
}

Input & Output

fxpimu
fxpimu
0

fxpimu
xwrs
5

fxpimu
f
5

fxpimu
im
4

fxpimu
iq
5

Reference

王晓东《计算机算法设计与分析》(第3版)P89-90

猜你喜欢

转载自blog.csdn.net/ioio_/article/details/81008574
今日推荐