您的位置:首页 > 其它

文本相似度计算之--- 编辑距离 && 最长公共子串

2014-09-02 14:19 295 查看
问题引入:在自然语言处理领域里,求文本相似度是最基本的问题,对于这个问题,可以分为大的两类,一种是基于字符串层次的相似度计算,一种是基于语义的相似度计算。我会循序渐进的讲给大家。

本文我们先来看最简单的两种基于字符串层面的相似度度量算法。

1. 最长公共子串

对于最长公共子串,不难想象,就是要求两个字符串中出现的共同字符部分,并且这些字符必须是连续的,比如,aaabcdeff和bcdffab,那么他们最长的公共子串即是bcd,长度为3,其实问题很简单,大家可以这么想,如果两个字符串的公共子串存在,那么可以有如下的推导:s1, s2为两个字符串,cnt为子串长度的计数数组,则:

if   s1[i] == s2[j]   ,   cnt[j]=cnt[j-1]+1;

else   cnt[j]=0;

此处我们设置maxlen标记最大长度,若有cnt[j]>maxlen,则maxlen=cnt[j],然后记录位置j,以便可以输出最长公共子串。

下面附上代码:

public class Test{
public void findLCS(String s1,String s2){
int len1 = s1.length();
int len2 = s2.length();
char[] cs1 = s1.toCharArray();
char[] cs2 = s2.toCharArray();
int[] cnt = new int[100];
int maxlen = 0;
int pos = 0;
for(int i=0;i<len1;++i){
for(int j=len2;j>0;--j){//这里逆向遍历是为了防止覆盖cnt数组之前记录的结果,想不明白的话请在纸上模拟一下
if(cs1[i]==cs2[j-1]){
cnt[j]=cnt[j-1]+1;
if(cnt[j]>maxlen){
maxlen=cnt[j];
pos=j;
}
}else{
cnt[j]=0;
}
}
}
System.out.println(maxlen);
for(int i=0;i<maxlen;++i){
System.out.print(cs2[pos-maxlen+i]);//输出最长公共子串
}
}
public static void main(String[] args){
String s1="abcdefg";
String s2="aaabcfff";
Test test = new Test();
test.findLCS(s1, s2);
}
}
2. 编辑距离

对于编辑距离,就是说对于两个字符串s1和s2,我们要计算出从s1转换成s2所用的最小步数,转换操作只能是替换一个字符,插入一个字符,删除一个字符。

我们用edit(i,j)表示s1的长度为i的子串到s2的长度为j的子串的编辑距离,那么不难推导出:

if i==0 && j==0,edit(i,j)=0 --- (1)

if i==0 && j>0,edit(i,j)=j 因为s1此时的子串长度为0,从长度为0的串变到s2长度为j的串,当然要j歩了,对吧 --- (2)

if i>0 && j==0,edit(i,j)=i 同上理由 --- (3)

if i>0 && j>0,edit(i,j)=min{edit(i-1,j)+1,edit(i,j-1)+1,edit(i-1,j-1)+flag},其中若s1i != s2j,则flag=1,否则flag=0,这个不难理解吧?若不理解可以留言 --- (4)

附上代码,注意初始化时,edit(i,0)=i,edit(0,j)=j,对应于上述(2)(3)条:

public class EditDistance {
int[][] edit;
public EditDistance(){

}
public int getEditDistance(String s1,String s2){
int l1=s1.length();
int l2=s2.length();
int f;
char[] st1,st2;
edit = new int[l1+1][l2+1];

for
4000
(int i = 0;i<=l1;++i){
edit[i][0]=i;
}
for(int i = 0;i<=l2;++i){
edit[0][i]=i;
}
for(int i=0;i<l1;++i){
for(int j=0;j<l2;++j){
st1 = s1.toCharArray();
st2 = s2.toCharArray();
if(st1[i]==st2[j])f=0;
else f=1;
edit[i+1][j+1]=Math.min(edit[i][j+1]+1, edit[i+1][j]+1);
edit[i+1][j+1]=Math.min(edit[i+1][j+1], edit[i][j]+f);
}
}
return edit[l1][l2];
}
public static void main(String[] args){
EditDistance ed = new EditDistance();
int result = ed.getEditDistance("ababab","bababa");
System.out.println(result);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐