您的位置:首页 > 编程语言 > Java开发

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

2016-03-23 21:06 441 查看
问题:给定一个源串和目标串,能够对源串进行如下操作:

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

替换任意字符

删除任意字符

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

 

关于编辑距离

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

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

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

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

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

那么边界条件:

d[i][0]=i, 0=<i<=m

d[0][j]=j, 0=<j<=n

状态转移方程: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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: