【动态规划】字符串最小编辑距离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实现:
测试用例:
运行结果:
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
在给定位置上插入一个字符
替换任意字符
删除任意字符
要求写一个程序,返回最少的操作数,使得对源串进行这些操作后等于目标串。源串和目标串的长度都小于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
相关文章推荐
- eclipse设置自动换行
- java中equals方法的用法以及==的用法
- 40个Java多线程问题总结
- Struts.xml 中的11种Result-Type类型
- Java对数组对象进行排序
- 哈夫曼树及一种java实现
- Spring的IOC逐层深入——依赖注入的两种实现类型
- Java基础之内部类
- kettle源码
- 父类私有变量是否被子类继承详细解说(答案:内存中存在,但sun公司定义为不继承)
- java学习资源
- 开发高性能JAVA应用程序基础(集合篇)
- java中新起一个线程
- Struts2文件上传与下载
- java set间的相互转换
- ETL工具kettle源码解读-前言
- 为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?
- java 实现打印杨辉三角
- SSM框架Web程序的流程(Spring SpringMVC Mybatis)
- java中代码执行顺序(静态代码块、构造函数)