计算字符串相似度的简易算法 -凯发k8网页登录

java, c , linux c, c#.net 技术,软件架构,领域建模,it 项目管理

 

计算字符串相似度的简易算法

算法设计背景:

最近设计知识管理系统的资源导入功能,为了尽量的做到组件化,方便扩展,方便其他模块使用。简化组件提供的和需要的接口,设计并实现了基于 mapping 机制的导入框架。其中有一功能用到了计算两个字符串相似度的算法,简单设计如下以便参考:

设计思想:

   把两个字符串变成相同的基本操作定义如下:

1.     修改一个字符(如把 a 变成 b

2.     增加一个字符 ( abed 变成 abedd)

3.     删除一个字符(如 jackbllog 变成 jackblog

针对于 jackbllogjackblog 只需要删除一个或增加一个 l 就可以把两个字符串变为相同。把这种操作需要的次数定义为两个字符串的距离 l, 则相似度定义为 1/(l 1) 即距离加一的倒数。那么jackbllogjackblog的相似度为 1/1 1=1/2=0.5 也就是所两个字符串的相似度是 0.5,说明两个字符串已经很接近啦。

任意两个字符串的距离都是有限的,都不会超过他们的长度之和,算法设计中我们并不在乎通过一系列的修改后,得到的两个相同字符串是什么样子。所以每次只需一步操作,并递归的进行下一计算。java 的实现如下:

 1/**
 2 * 
 3 */

 4package org.blogjava.arithmetic;
 5
 6import java.util.hashmap;
 7import java.util.map;
 8
 9/**
10 * @author jack.wang
11 * 
12 */

13public class stringdistance {
14
15    public static final map<string, string> distance_cache = new hashmap<string, string>();
16
17    private static int caculatestringdistance(byte[] firststr, int firstbegin,
18            int firstend, byte[] secondstr, int secondbegin, int secondend) {
19        string key = makekey(firststr, firstbegin, secondstr, secondbegin);
20        if (distance_cache.get(key) != null{
21            return integer.parseint(distance_cache.get(key));
22        }
 else {
23            if (firstbegin >= firstend) {
24                if (secondbegin >= secondend) {
25                    return 0;
26                }
 else {
27                    return secondend - secondbegin  1;
28                }

29            }

30            if (secondbegin >= secondend) {
31                if (firstbegin >= firstend) {
32                    return 0;
33                }
 else {
34                    return firstend - firstbegin  1;
35                }

36            }

37            if (firststr[firstbegin] == secondstr[secondbegin]) {
38                return caculatestringdistance(firststr, firstbegin  1,
39                        firstend, secondstr, secondbegin  1, secondend);
40            }
 else {
41                int onevalue = caculatestringdistance(firststr, firstbegin  1,
42                        firstend, secondstr, secondbegin  2, secondend);
43                int twovalue = caculatestringdistance(firststr, firstbegin  2,
44                        firstend, secondstr, secondbegin  1, secondend);
45                int threevalue = caculatestringdistance(firststr,
46                        firstbegin  2, firstend, secondstr, secondbegin  2,
47                        secondend);
48                distance_cache.put(key, string.valueof(min(onevalue, twovalue,
49                        threevalue)  1));
50                return min(onevalue, twovalue, threevalue)  1;
51            }

52        }

53    }

54
55    public static float similarity(string stringone, string stringtwo) {
56        return 1f / (caculatestringdistance(stringone.getbytes(), 0, stringone
57                .getbytes().length - 1, stringtwo.getbytes(), 0, stringone
58                .getbytes().length - 1 1);
59    }

60
61    private static int min(int onevalue, int twovalue, int threevalue) {
62        return onevalue > twovalue ? twovalue
63                : onevalue > threevalue ? threevalue : onevalue;
64    }

65
66    private static string makekey(byte[] firststr, int firstbegin,
67            byte[] secondstr, int secondbegin) {
68        stringbuffer sb = new stringbuffer();
69        return sb.append(firststr).append(firstbegin).append(secondstr).append(
70                secondbegin).tostring();
71    }

72
73    /**
74     * @param args
75     */

76    public static void main(string[] args) {
77        float i = stringdistance.similarity("jacklovvedyou""jacklodveyou");
78        system.out.println(i);
79    }

80}

81




本博客为学习交流用,凡未注明引用的均为本人作品,转载请注明出处,如有凯发k8网页登录的版权问题请及时通知。由于博客时间仓促,错误之处敬请谅解,有任何意见可给我留言,愿共同学习进步。
posted on 2009-01-19 23:53 jack.wang 阅读(10864) 评论(9)  编辑  收藏 所属分类: 开发技术数学&算法
# re: 计算字符串相似度的简易算法 2009-01-20 09:37
看看算法书再来吧  回复  
  

# re: 计算字符串相似度的简易算法[未登录] 2009-01-20 10:44
使用向量吧。  回复  
  

# re: 计算字符串相似度的简易算法 2009-01-20 10:59
字符串不是字节流
相似度是不好这样简单算的
比如
helloworld
hollywood
9个字母里面就有6个相同
显然不是那么简单回事  回复  
  

# re: 计算字符串相似度的简易算法 2009-01-20 16:29
计算编辑距离是个好想法,但还是有局限性的

另外你的相似度计算公式从分布上并不很natural,比如两个长度在30的单词,如果编辑距离为1,他们的相似度会比两个长度在5编辑距离为1的单词要更加高一些(我觉得这样的想法会更natural一点)。

从编辑距离本身的定义角度,我觉得还是不适合作为字符串相似的量度的,但可以作为辅助手段来对可能的错误输入产生提示。  回复  
  

# re: 计算字符串相似度的简易算法 2009-01-20 20:21 jack.wang
这么多人回复啊!
@anonymous
恩,说的很好,谢谢啦!之前没看相关的算法书,只是有这个想法!顺便写了写!应该有更好的量度来计算两个字符串的相似度!等看看算法书或者有 blog 友贴贴!  回复  
  

# re: 计算字符串相似度的简易算法 2009-08-29 23:41
递归算法的复杂度非常高,动态规划算法能把复杂度降到o(m*n),改进后能到o(n k^2),自动机和bit-parallelism算法甚至能到o(n)  回复  
  

# re: 计算字符串相似度的简易算法 2009-10-14 14:54
有那么简单么……  回复  
  

# re: 计算字符串相似度的简易算法 2009-12-17 14:02
是的,使用编辑距离(尤其是改良后的levenshtein算法)其算法复杂度可以缩短至o(2k 1)。不过lz的思想和levenshtein算法的初衷本质上是一致的,还是值得赞赏的,可惜人家比你早很多年提出来~  回复  
  

# re: 计算字符串相似度的简易算法 2010-03-25 09:18
老大,这是《编程之美》上的原题源代码  回复  
  

网站地图