【动态规划】字符串最小编辑距离Java实现

问题:给定一个源串和目标串,能够对源串进行如下操作:

在给定位置上插入一个字符

替换任意字符

删除任意字符

要求写一个程序,返回最少的操作数,使得对源串进行这些操作后等于目标串。源串和目标串的长度都小于2000

 

关于编辑距离

编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符。

例如:字符串abc和字符串adbe之间的最小编辑距离是2 因为adbe删除b然后将e替换为c经过这两部


a[m]表示第一个字符串,m表示该字符串字符的下标为0~m

b[n]表示第二个字符串,n表示该字符串字符的下标为0~n

d[i][j]表示子串a[i]和子串a[j]的最小编辑距离

那么边界条件:

d[i][0]=i, 0=

d[0][j]=j, 0=

状态转移方程:d[i][j]=min{d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+lastCharCommon}

lastCharCommon=1,如果a[i-1]等于b[j-1]

lastCharCommon=0,如果a[i-1]不等于b[j-1]

下边给出java实现:

class StringEditDistance{
    /*输入两个字符串,返回这两个字符串的编辑距离*/
    public static int getDistance(String strA, String strB){
        int distance=-1;
        /*输入参数合法性检查*/
        if(null==strA||null==strB||strA.isEmpty()||strB.isEmpty()){
            return distance;
        }
        /*两个字符串相等,编辑距离为0*/
        if (strA.equals(strB)) {
            return 0;
        }
        System.out.println("第一个字符串:"+strA);
        System.out.println("第二个字符串:"+strB);
        int lengthA=strA.length();
        int lengthB=strB.length();
        int length=Math.max(lengthA,lengthB);
        /*申请一个二维数组,存储转移矩阵*/
        int array[][]=new int[length+1][length+1];
        /*边界条件初始化*/
        for(int i=0;i<=length;i++){
            array[i][0]=i;

        }
        /*边界条件初始化*/
        for(int j=0;j<=length;j++){
            array[0][j]=j;
        }
        /*状态转移方程*/
        for(int i=1;i<=lengthA;i++){
            for(int j=1;j<=lengthB;j++){
                array[i][j]=min(array[i-1][j]+1,
                                array[i][j-1]+1,
                                array[i-1][j-1]+(strA.charAt(i-1)==strB.charAt(j-1)?0:1));
            }
        }
        /*打印转移表格*/
        System.out.println("状态转移表格:");
        for(int i=0;i<=lengthA;i++){
            for(int j=0;j<=lengthB;j++){
               System.out.print( array[i][j]+"    ");
            }
            System.out.println();
        }
        return array[lengthA][lengthB];

    }
    /*取三个数中的最小值*/
    public static int  min(int a,int b, int c){
        return Math.min(Math.min(a,b),c);
    }
}

测试用例:

String a=null;
String b="abd";

System.out.println("case 1:编辑距离为:"+StringEditDistance.getDistance(a,b));
System.out.println();

a="Program";
b="P-r-o-g-r-a-m";
System.out.println("case 2:编辑距离为"+StringEditDistance.getDistance(a,b));
System.out.println();

a="2333";
b="6666666";
System.out.println("case 3:编辑距离为"+StringEditDistance.getDistance(a,b));
System.out.println();

a="adbe";
b="abc";
System.out.println("case 4:编辑距离为"+StringEditDistance.getDistance(a,b));
System.out.println();

a="hehe";
b="hehe";
System.out.println("case 5:编辑距离为"+StringEditDistance.getDistance(a,b));
System.out.println();


运行结果:


case 1:编辑距离为:-1


第一个字符串:Program
第二个字符串:P-r-o-g-r-a-m
状态转移表格:
0    1    2    3    4    5    6    7    8    9    10    11    12    13    
1    0    1    2    3    4    5    6    7    8    9    10    11    12    
2    1    1    1    2    3    4    5    6    7    8    9    10    11    
3    2    2    2    2    2    3    4    5    6    7    8    9    10    
4    3    3    3    3    3    3    3    4    5    6    7    8    9    
5    4    4    3    4    4    4    4    4    4    5    6    7    8    
6    5    5    4    4    5    5    5    5    5    5    5    6    7    
7    6    6    5    5    5    6    6    6    6    6    6    6    6    
case 2:编辑距离为6


第一个字符串:2333
第二个字符串:6666666
状态转移表格:
0    1    2    3    4    5    6    7    
1    1    2    3    4    5    6    7    
2    2    2    3    4    5    6    7    
3    3    3    3    4    5    6    7    
4    4    4    4    4    5    6    7    
case 3:编辑距离为7


第一个字符串:adbe
第二个字符串:abc
状态转移表格:
0    1    2    3    
1    0    1    2    
2    1    1    2    
3    2    1    2    
4    3    2    2    
case 4:编辑距离为2


case 5:编辑距离为0

你可能感兴趣的:(Java基础)