编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数。许可的编辑操作包括将一个
字符
替换成另一个字符,插入一个字符,删除一个字符。一般来说,编辑距离越小,两个串的相似度越大。
例如将kitten一字转成sitting:
sitten (k→s)
sittin (e→i)
sitting (→g)
比如要计算cafe和coffee的编辑距离。cafe→caffe→coffe→coffee
先创建一个6×8的表(cafe长度为4,coffee长度为6,各加2)
(1):
c | o | f | f | e | e | ||
c | |||||||
a | |||||||
f | |||||||
e | 表 | 1 |
接着,在如下位置填入数字(表2):
c | o | f | f | e | e | ||
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
c | 1 | ||||||
a | 2 | ||||||
f | 3 | ||||||
e | 4 | 表 | 2 |
从3,3格开始,开始计算。取以下三个值的最小值:
-
如果最上方的字符等于最左方的字符,则为左上方的数字。否则为左上方的数字+1。(对于3,3来说为0)
-
左方数字+1(对于3,3格来说为2)
-
上方数字+1(对于3,3格来说为2)
因此为格3,3为0(表3)
c | o | f | f | e | e | ||
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
c | 1 | 0 | |||||
a | 2 | ||||||
f | 3 | ||||||
e | 4 | 表 | 3 |
循环操作,推出下表
c | o | f | f | e | e | ||
0 | 1 | 2 | 3 | 4 | 5 | 6 | |
c | 1 | 0 | 1 | 2 | 3 | 4 | 5 |
a | 2 | 1 | 1 | 2 | 3 | 4 | 5 |
f | 3 | 2 | 2 | 1 | 2 | 3 | 4 |
e | 4 | 3 | 3 | 2 | 2 | 2 | 3 |
取右下角,得编辑距离为3
代码实现如下:
import java.util.Scanner;
import java.util.regex.Pattern;
public class Test{
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String s1=input.nextLine();
String s2=input.nextLine();
compare(s1,s2);
input.close();
}
public static void compare(String s1,String s2){
int m=s1.length();
int n=s2.length();
int c[][]=new int[m+1][n+1];
for(int i=0;i<m+1;i++){
c[0][i]=i;
}
for(int j=0;j<n+1;j++){
c[j][0]=j;
}
for(int i=1;i<m+1;i++){
for(int j=1;j<n+1;j++){
if(s1.charAt(i-1)==s2.charAt(j-1)){
c[i][j]=min(c[i-1][j]+1,c[i][j-1]+1,c[i-1][j-1]);
}else{
c[i][j]=min(c[i-1][j]+1,c[i][j-1]+1,c[i-1][j-1]+1);
}
}
}
System.out.println("****");
for(int i=0;i<m+1;i++){
for(int j=0;j<n+1;j++){
System.out.print(c[i][j]+" ");
}
System.out.println("");
}
System.out.println("****");
}
public static int min(int a,int b,int c){
return a<b?(a<c?a:c):(b>c?c:b);
}
}