levenshtein distanceld计算两字符串相似度算法chenlb.docx
《levenshtein distanceld计算两字符串相似度算法chenlb.docx》由会员分享,可在线阅读,更多相关《levenshtein distanceld计算两字符串相似度算法chenlb.docx(9页珍藏版)》请在冰豆网上搜索。
levenshteindistanceld计算两字符串相似度算法chenlb
LevenshteinDistance(LD)-计算两字符串相似度算法-chenlb...
LevenshteinDistance(LD)-计算两字符串相似度算法
关键字:
字符串相似度算法ld
两字符串相似度计算方法有好多,现对基于编距的算法的相似度计算自己总结下。
简单介绍下LevenshteinDistance(LD):
LD可能衡量两字符串的相似性。
它们的距离就是一个字符串转换成那一个字符串过程中的添加、删除、修改数值。
举例:
如果str1="test",str2="test",那么LD(str1,str2)=0。
没有经过转换。
如果str1="test",str2="tent",那么LD(str1,str2)=1。
str1的"s"转换"n",转换了一个字符,所以是1。
如果它们的距离越大,说明它们越是不同。
Levenshteindistance最先是由俄国科学家VladimirLevenshtein在1965年发明,用他的名字命名。
不会拼读,可以叫它editdistance(编辑距离)。
Levenshteindistance可以用来:
Spellchecking(拼写检查)
Speechrecognition(语句识别)
DNAanalysis(DNA分析)
Plagiarismdetection(抄袭检测)
LD用m*n的矩阵存储距离值。
算法大概过程:
str1或str2的长度为0返回另一个字符串的长度。
初始化(n+1)*(m+1)的矩阵d,并让第一行和列的值从0开始增长。
扫描两字符串(n*m级的),如果:
str1[i]==str2[j],用temp记录它,为0。
否则temp记为1。
然后在矩阵d[i][j]赋于d[i-1][j]+1、d[i][j-1]+1、d[i-1][j-1]+temp三者的最小值。
扫描完后,返回矩阵的最后一个值即d[n][m]
最后返回的是它们的距离。
怎么根据这个距离求出相似度呢?
因为它们的最大距离就是两字符串长度的最大值。
对字符串不是很敏感。
现我把相似度计算公式定为1-它们的距离/字符串长度最大值。
源码:
Java代码
packagecom.chenlb.algorithm;
/**
*编辑距离的两字符串相似度
*
*@authorchenlb2008-6-24下午06:
41:
55
*/
publicclassSimilarity{
privateintmin(intone,inttwo,intthree){
intmin=one;
if(two<min){
min=two;
}
if(three<min){
min=three;
}
returnmin;
}
publicintld(Stringstr1,Stringstr2){
intd[][];//矩阵
intn=str1.length();
intm=str2.length();
inti;//遍历str1的
intj;//遍历str2的
charch1;//str1的
charch2;//str2的
inttemp;//记录相同字符,在某个矩阵位置值的增量,不是0就是1
if(n==0){
returnm;
}
if(m==0){
returnn;
}
d=newint[n+1][m+1];
for(i=0;i<=n;i++){//初始化第一列
d[i][0]=i;
}
for(j=0;j<=m;j++){//初始化第一行
d[0][j]=j;
}
for(i=1;i<=n;i++){//遍历str1
ch1=str1.charAt(i-1);
//去匹配str2
for(j=1;j<=m;j++){
ch2=str2.charAt(j-1);
if(ch1==ch2){
temp=0;
}else{
temp=1;
}
//左边+1,上边+1,左上角+temp取最小
d[i][j]=min(d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+temp);
}
}
returnd[n][m];
}
publicdoublesim(Stringstr1,Stringstr2){
intld=ld(str1,str2);
return1-(double)ld/Math.max(str1.length(),str2.length());
}
publicstaticvoidmain(String[]args){
Similaritys=newSimilarity();
Stringstr1="";
Stringstr2="";
System.out.println("ld="+s.ld(str1,str2));
System.out.println("sim="+s.sim(str1,str2));
}
}
packagecom.chenlb.algorithm;
/**
*编辑距离的两字符串相似度
*
*@authorchenlb2008-6-24下午06:
41:
55
*/
publicclassSimilarity{
privateintmin(intone,inttwo,intthree){
intmin=one;
if(two<min){
min=two;
}
if(three<min){
min=three;
}
returnmin;
}
publicintld(Stringstr1,Stringstr2){
intd[][];//矩阵
intn=str1.length();
intm=str2.length();
inti;//遍历str1的
intj;//遍历str2的
charch1;//str1的
charch2;//str2的
inttemp;//记录相同字符,在某个矩阵位置值的增量,不是0就是1
if(n==0){
returnm;
}
if(m==0){
returnn;
}
d=newint[n+1][m+1];
for(i=0;i<=n;i++){//初始化第一列
d[i][0]=i;
}
for(j=0;j<=m;j++){//初始化第一行
d[0][j]=j;
}
for(i=1;i<=n;i++){//遍历str1
ch1=str1.charAt(i-1);
//去匹配str2
for(j=1;j<=m;j++){
ch2=str2.charAt(j-1);
if(ch1==ch2){
temp=0;
}else{
temp=1;
}
//左边+1,上边+1,左上角+temp取最小
d[i][j]=min(d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+temp);
}
}
returnd[n][m];
}
publicdoublesim(Stringstr1,Stringstr2){
intld=ld(str1,str2);
return1-(double)ld/Math.max(str1.length(),str2.length());
}
publicstaticvoidmain(String[]args){
Similaritys=newSimilarity();
Stringstr1="";
Stringstr2="";
System.out.println("ld="+s.ld(str1,str2));
System.out.println("sim="+s.sim(str1,str2));
}
}
不知sim方法中的公式是合理,个人认为差强人意思,不知javaeyer们,有没有高见,指点一二,^_^
参考:
1
顶
0
踩18:
46
浏览(1198)
评论
(2)
分类:
algorithm
发布在lucene爱好者圈子
相关推荐评论
chenlb2008-06-27回复
抄袭检测是,参考:
里面说的,此算法在聚类应用中还算可以.抄袭,用关键词余弦定理(向量空间模型),应该比较好.我的毕业设计就做了这方面的功能.就是用向量项.它的缺点就是不检测结构上的相似,当关键字相同时,把顺序倒过来,相似度还是一样.但正常情况可能满足了.
minstrel2008-06-26回复
我觉得这个在检查抄袭上估计不行,这个方法好像更关注交换程度,因为抄袭是关键词差不多的,监测抄袭还是google那个余弦(cos)方法更合理