简单实现
public class DamerauLevenshteinDistance {
private int getDistance(String s1,String s2){
int m= (s1==null)?0:s1.length();
int n= (s2==null)?0:s2.length();
if(m==0){
return n;
}
if(n==0){
return m;
}
int[][] d=new int[m+1][n+1];
for(int i=0;i<=m;i++){
d[i][0]=i;
}
for(int i=1;i<=n;i++){
d[0][i]=i;
}
char s1_c,s2_c;
int cost=0;
for(int i=1;i<=m;i++){
s1_c=s1.charAt(i-1);
for(int j=1;j<=n;j++){
s2_c=s2.charAt(j-1);
cost=(s1_c==s2_c)?0:1;
d[i][j]=Math.min(Math.min(d[i-1][j],d[i][j-1])+1,d[i-1][j-1]+cost);
if(i>=2&&j>=2&&s1_c==s2.charAt(j-2)&&s1.charAt(i-2)==s2_c){
d[i][j]=Math.min(d[i][j], d[i-2][j-2]+cost);
}
}
}
return d[m][n];
}
public float getSimilarity(String s1,String s2){
if(s1==null||s2==null){
if(s1==s2){
return 1.0f;
}
return 0.0f;
}
float d=getDistance(s1,s2);
return 1-(d/Math.max(s1.length(), s2.length()));
}
}
优化后
public class DamerauLevenshteinDistance2 {
private int getDistance(String s1,String s2){
int m= (s1==null)?0:s1.length();
int n= (s2==null)?0:s2.length();
if(m==0){
return n;
}
if(n==0){
return m;
}
int[] p=new int[n+1];
int[] p1=new int[n+1];
int[] t=new int[n+1];
for(int i=0;i<p.length;i++){
p[i]=i;
}
int d=0;
int cost=0;
char s1_c,s2_c;
for(int i=0;i<m;i++){
t[0]=i+1;
s1_c=s1.charAt(i);
for(int j=1;j<p.length;j++){
s2_c=s2.charAt(j-1);
cost=(s1_c==s2_c)?0:1;
d=Math.min(Math.min(t[j-1],p[j])+1,p[j-1]+cost);
if(i>0&&j>1&&s1_c==s2.charAt(j-2)&&s1.charAt(i-1)==s2_c){
d=Math.min(d,p1[j-2]+cost);
}
t[j]=d;
}
p1=p;
p=t;
t=new int[n+1];
}
return d;
}
public float getSimilarity(String s1,String s2){
if(s1==null||s2==null){
if(s1==s2){
return 1.0f;
}
return 0.0f;
}
float d=getDistance(s1,s2);
return 1-(d/Math.max(s1.length(), s2.length()));
}
}
简单测试
import org.junit.Test;
public class DamerauLevenshteinDistanceTest {
@Test
public void testGetSimilarity() {
String s1="aborad";
String s2="aboard";
DamerauLevenshteinDistance dld=new DamerauLevenshteinDistance();
System.out.println(dld.getSimilarity(s1, s2));
DamerauLevenshteinDistance2 dld2=new DamerauLevenshteinDistance2();
System.out.println(dld2.getSimilarity(s1, s2));
}
}