字符串相似度计算

对于编辑距离为1的字符串,我们只需要通过一次操作(添加、删除或修改)一个字符可以使得两个字符串相等。

使用递归来计算编辑距离。

  
  
  
  
  1. package stringsimilarity;  
  2.  
  3. public class SimilarityFactory {  
  4.     public static int getDistance(String a, String b){  
  5.         if(a.length()==0){  
  6.             return b.length();  
  7.         }  
  8.         if(b.length()==0){  
  9.             return a.length();  
  10.         }  
  11.         if(a.charAt(0)==b.charAt(0)){  
  12.             return getDistance(a.substring(1),b.substring(1));  
  13.         }else{  
  14.             int s1= getDistance(a,b.substring(1));  
  15.             int s2= getDistance(a.substring(1),b);  
  16.             int s3= getDistance(a.substring(1),b.substring(1));  
  17.             int min = s1;  
  18.             if(s2<min)  
  19.                 min= s2;  
  20.             if(s3<min)  
  21.                 min= s3;  
  22.             return min+1;  
  23.         }  
  24.     }  
  25.       
  26.     public static double getSimilarity(String a, String b){  
  27.         int d = getDistance(a,b);  
  28.         return 1.0/(d+1);  
  29.     }  
  30.  
  31. }  

上述程序可以改进

1. 将字符串传递参数换成传递char数组指针

  
  
  
  
  1. public static double getSimilarity2(String a, String b){  
  2.     //int d = getDistance(a,b);  
  3.     int d = getDistance(a.toCharArray(),0,b.toCharArray(),0);  
  4.     return 1.0/(d+1);  
  5. }  
  6. public static int getDistance(char[] a, int beginA, char[] b, int beginB){  
  7.     if(a.length - beginA ==0){  
  8.         return b.length - beginB;  
  9.     }  
  10.     if(b.length - beginB ==0){  
  11.         return a.length - beginA;  
  12.     }  
  13.     if(a[beginA]==b[beginB]){  
  14.         return getDistance(a, beginA+1, b, beginB+1);  
  15.     }else{  
  16.         int s1= getDistance(a, beginA, b, beginB+1);  
  17.         int s2= getDistance(a, beginA+1, b, beginB);  
  18.         int s3= getDistance(a, beginA+1, b, beginB+1);  
  19.         int min = s1;  
  20.         if(s2<min)  
  21.             min= s2;  
  22.         if(s3<min)  
  23.             min= s3;  
  24.         return min+1;  
  25.     }  

2. 在递归过程中有些递归调用是重复的,可以通过记录中间值避免重新计算

 可以使用HashMap来保存,或使用数组

  
  
  
  
  1. public static double getSimilarity4(String a, String b){  
  2.       
  3.     int[][] dis = new int[a.length()+1][b.length()+1];  
  4.     for(int i = 0;i<dis.length;i++){  
  5.         for (int j = 0; j < dis[0].length; j++)   
  6.             dis[i][j]=-1;  
  7.     }  
  8.     int d = getDistance3(a.toCharArray(),0,b.toCharArray(),0, dis);  
  9.     return 1.0/(d+1);  
  10. }  
  11.  
  12. public static int getDistance3(char[] a, int beginA, char[] b, int beginB, int[][] dis){  
  13.     if(a.length - beginA ==0){  
  14.         return b.length - beginB;  
  15.     }  
  16.     if(b.length - beginB ==0){  
  17.         return a.length - beginA;  
  18.     }  
  19.     if(a[beginA]==b[beginB]){  
  20.         int s = dis[beginA+1][beginB+1];  
  21.         if(s == -1){  
  22.             s = getDistance3(a, beginA+1, b, beginB+1,dis);   
  23.             dis[beginA+1][beginB+1] = s;  
  24.         }  
  25.         return s;  
  26.     }else{  
  27.         int s1 = dis[beginA][beginB+1];  
  28.         if(s1 == -1){  
  29.           s1= getDistance3(a, beginA, b, beginB+1,dis);   
  30.           dis[beginA][beginB+1] = s1;  
  31.         }  
  32.  
  33.         int s2 = dis[beginA+1][beginB];  
  34.         if(s2 == -1){  
  35.             s2= getDistance3(a, beginA+1, b, beginB,dis);  
  36.             dis[beginA+1][beginB] = s2;  
  37.         }  
  38.           
  39.           
  40.         int s3 = dis[beginA+1][beginB+1];  
  41.         if(s3 == -1){  
  42.             s3= getDistance3(a, beginA+1, b, beginB+1,dis);  
  43.             dis[beginA+1][beginB+1] = s3;  
  44.         }  
  45.         int min = s1;  
  46.         if(s2<min)  
  47.             min= s2;  
  48.         if(s3<min)  
  49.             min= s3;  
  50.         return min+1;  
  51.     }  

 测试:

  
  
  
  
  1. package stringsimilarity;  
  2.  
  3. import junit.framework.TestCase;  
  4.  
  5. public class TestSimilarity extends TestCase {  
  6.       
  7.     public void testSimilarity1(){//添加一个字符  
  8.         String a = "traveling";  
  9.         String b = "travelling";  
  10.         double s = SimilarityFactory.getSimilarity(a, b);  
  11.         System.out.println(s);  
  12.         assertEquals(s,0.5);  
  13.     }  
  14.       
  15.     public void testSimilarity2(){//删除一个字符  
  16.         String a = "about";  
  17.         String b = "bout";  
  18.         double s = SimilarityFactory.getSimilarity(a, b);  
  19.         System.out.println(s);  
  20.         assertEquals(s,0.5);  
  21.     }  
  22.       
  23.     public void testSimilarity3(){//修改一个字符  
  24.         String a = "flying";  
  25.         String b = "flyong";  
  26.         double s = SimilarityFactory.getSimilarity(a, b);  
  27.         System.out.println(s);  
  28.         assertEquals(s,0.5);  
  29.     }  
  30.       
  31.     public void testSimilarity4(){//修改一个字符  
  32.         long start = System.currentTimeMillis();  
  33.         String a = "appidimiologist";  
  34.         String b = "epidemiologist";  
  35.         //double s = SimilarityFactory.getSimilarity(a, b);//传字符串作参数21.734s  
  36.         //double s = SimilarityFactory.getSimilarity2(a, b);//传char数组引用6.141s  
  37.         //double s = SimilarityFactory.getSimilarity3(a, b);//使用hashmap保持计算过的值  
  38.         double s = SimilarityFactory.getSimilarity4(a, b);//使用数组保存计算过的值0.015s  
  39.         System.out.println("result:"+s);  
  40.         assertEquals(s,0.25);  
  41.  
  42.         long end = System.currentTimeMillis();  
  43.  
  44.         System.out.println("Total time:"+ (end - start)/1000.0);  
  45.           
  46.     }  
  47.  
  48. }  

改进后运行时间效率有很大的改善。

你可能感兴趣的:(字符串,职场,相似度,休闲)