原文地址:http://www.jmatrix.org/algorithm/166.html
字符串相似度计算是查找两个字符串的公共子串,利用公共子串的长度根据相应的公式来衡量两个字符串的相似程度。字符串相似度计算算法很多,如LCS算法、Levenshtein Distance算法、Heckel算法、GST算法等。对于历经N次笔试面试的人来说,这个再熟悉不过了。应要求,要帮忙写个计算两字符串相似度的算法,所以我特意去看了篇论文,并据此实现LCS与GST算法。
1. 概念
LCS(最长公共子序列)算法是将两个给定字符串分别删去0个或多个字符,但不改变剩余字符串的顺序后得到的长度最长的相同字符序列。给定字符串P、T、X,X称为P和T的最长公共子序列是指X是P和T的公共子序列,且对于P和T的任意公共子序列W,都有W<=X。
GST(Greedy String Tiling)算法是一种贪婪串匹配算法,这一算法对两个字符串进行贪婪式搜索以找出最大公有子串,它需要对要计算的两个字符串进行多次搜索,每次找出当前字符串中未“标注”部分的最长公共子串,并把找出的最长公共子串“标注”为已使用,避免最大匹配重复使用。
以“abcdefghijklmuvwxyz”与“ijkabclmdefghpq”为例解释GST的搜索过程:
(1)假如我们设最小匹配长度为2。第一次搜寻过程,先找到abc,此时最大匹配长度是3,之后找到defgh,因此它的长度大于3,所以此时最大匹配长度5,之后找到ijk,由于其长度小于5,放弃,最后是lm,其长度同样小于当前最大匹配长度5,放弃。
(2)将(1)中找到的最大匹配子串”标注为已使用“,重复(1)的过程,不过不再对”已标注子串“搜索,直到(1)中找到的最大匹配子串的长度为设置的最小匹配长度。
2. 应用场景
从上面的介绍中,可以看出LCS与GST的一个重要区别就是LCS得到的最大公共子串是严格有序的,对于一些顺序调换的情况,它计算出的相似度是比较低的,相反,GST并不要求其子串严格有序,只有存在相等子串,及时位置不对也可找到,因此相对来说,它计算出的相似度更高。
在分析生物学领域,DNA分子常被表示成一个字符串,两个DNA分子之间的相似性常用它们共同包含的碱基对的序列长度来度量,这是最长公共子序列应用最广泛的领域,LCS还可以应用于数据压缩、文件比较、语言识别等方面。GST算法在信息检索、文本编辑、信息提取等领域有重要的应用。
3. 算法实现。
这里先给出别人的算法伪码,之后使用Java简单的实现一下相应的算法。
3.1 LCS算法实现
对于LCS的实现,总所周知是采用动态规划,用C(i, j )表示长度为i的字符创P与长度为j的T的最优值,也即最长公共子串长度,递推式为:
- 当i=0或j=0时,C(i, j)=0;
- 当i,j>0且pi=qj时, C(i, j) = C(i+1, j+1) + 1;
- 当i,j>0且pi不等于qj时, C(i, j) = max( C(i+1, j) , C(i, j+1) );
因此,计算C(i, j)的过程为:
int lcs_length( char* T, char* P){
for(i = m; i>=0;i–)
{
if(P[i] == ‘\0′ || T[j] ==’\0′)
C(i, j) = 0;
else if(P[i] == T[j])
C(i, j) = C(i+1, j+1) + 1;
else
C(i, j) = max( C(i+1, j) , C(i, j+1) );
}
}
之后,根据C得到最长公共子串的过程为:
S = {};
i = 0;
j = 0 ;
while( i<m && j<n){
if(P[i]==T[j]){
add T[j] to end of S;
i++; j++;
}
else if(C[i+1,j]>=C[i,j+1])
i++;
else
j++;
}
Java实现代码为:
public class Lcs { private int matchs[][] = null; public void calculateLength(String pwd1, String pwd2) { int len = pwd1.length() > pwd2.length() ? pwd1.length() : pwd2.length(); matchs = new int[len + 1][len + 1]; // init the match array. for (int i = 0; i <= pwd1.length(); i++) { for (int j = 0; j <= pwd2.length(); j++) { matchs[i][j] = 0; } } // calculate for (int i = pwd1.length(); i >= 0; i--) { for (int j = pwd2.length(); j >= 0; j--) { if (i == pwd1.length() || j == pwd2.length()) { matchs[i][j] = 0; } else if (pwd1.charAt(i) == pwd2.charAt(j)) matchs[i][j] = 1 + matchs[i + 1][j + 1]; else { matchs[i][j] = max(matchs[i + 1][j], matchs[i][j + 1]); } } } } public String getLCS(String pwd1, String pwd2){ StringBuffer buf = new StringBuffer(); int i = 0,j=0,len1=pwd1.length(),len2 = pwd2.length(); while(ithis.matchs[i][j+1]) i++; else j++; } return buf.toString(); } //计算相似度 public double calSimilarity(String pwd1, String pwd2){ int length = getLCS(pwd1, pwd2).length(); return (2.0*length)/(pwd1.length()+pwd2.length()); } private int max(int src, int des) { return src > des ? src : des; } }
3.2 GST算法实现
GST的搜索过程在”概念“部分已详细介绍,所以这里直接给Java实现代码:
public class Gst { private final int MIN_LENGTH = 2; List titles = new ArrayList(); List matchs = new ArrayList(); //GST算法实现 public void calculateGST(String pwd1, String pwd2) { int maxlength, count; int len1 = pwd1.length(); int len2 = pwd2.length(); // 辅助标记变量 int[] mark1 = new int[len1]; int[] mark2 = new int[len2]; for (int i = 0; i < len1; i++) mark1[i] = 0; for (int j = 0; j < len2; j++) mark2[j] = 0; // algorithm do { matchs.clear(); maxlength = MIN_LENGTH; for (int i = 0; i < len1; i++) { if (mark1[i] == 1) continue; for (int j = 0; j < len2; j++) { if (mark2[j] == 1) continue; count = 0; while (pwd1.charAt(i + count) == pwd2.charAt(j + count) && mark1[i + count] != 1 && mark2[j + count] != 1) { count++; } if(count==maxlength) this.matchs.add(new Stats(i, j, count)); else if(count>maxlength){ this.matchs.clear(); this.matchs.add(new Stats(i, j, count)); maxlength = count; } } } //标记阶段,标记前面找到的最大匹配,防止重复使用 for(Stats stats : this.matchs){ int pos1 = stats.getPosFirst(); int pos2 = stats.getPosSecond(); int length = stats.getLength(); for(int i=0;i<length;i++){ mark1[pos1+i]=1; mark2[pos2+i]=1; } this.titles.add(stats); } } while (maxlength != MIN_LENGTH); } class Stats { private int posFirst; private int posSecond; private int length; public Stats(int posM, int posN, int length) { this.posFirst = posM; this.posSecond = posN; this.length = length; } public int getPosFirst() { return posFirst; } public int getPosSecond() { return posSecond; } public int getLength() { return length; } } //输出找到的匹配串供测试 public String getTitles(String pwd1){ StringBuffer buf = new StringBuffer(); for(Stats stats : this.titles){ int pos1 = stats.getPosFirst(); int length = stats.getLength(); for(int i=0;i<length;i++){ buf.append(pwd1.charAt(pos1+i)); } buf.append("\t"); } return buf.toString(); } //计算相似度 public double calSimilarity(String pwd1,String pwd2){ int length = 0; String []vals = getTitles(pwd1).split("\t"); for(String val: vals){ length+=val.length(); } return (2.0*length)/(pwd1.length()+pwd2.length()); } }
相关推荐
字符串相似度算法 字符串相似度算法是一种衡量两个字符串之间相似度的方法,广泛应用于自然语言处理、数据挖掘、机器学习等领域。在本文中,我们将讨论一种常用的字符串相似度算法:Levenshtein Distance。 什么是...
在计算机科学领域,字符串相似度比较算法是一种用于评估两个字符串之间相似程度的技术。这些算法广泛应用于文本处理、信息检索、生物信息学等多个领域。当我们要判断两个字符串是否含有相同或相近的信息时,这类算法...
在IT领域,字符串相似度算法是一种非常重要的工具,特别是在数据挖掘、信息检索、文本分类以及自然语言处理等应用中。这个小例子旨在介绍如何通过计算字符串间的相似度来进行模糊匹配。我们将探讨几种常见的字符串...
《使用Delphi实现Levenshtein算法:计算字符串相似度》 在信息技术领域,字符串处理是常见的任务之一,其中计算两个字符串的相似度是尤为重要的一个环节。Levenshtein算法,也称为编辑距离算法,就是用于衡量两个...
Levenshtein算法,也称为编辑距离算法,是由俄国数学家Vladimir Levenshtein在1965年提出的一种衡量两个字符串相似度的方法。这个算法基于动态规划原理,可以计算出将一个字符串转换成另一个字符串所需要的最少单...
根据给定的文件信息,本文将详细介绍如何使用Java实现基于字符串的余弦相似度算法,并应用于推荐系统中。 ### 一、引言 在推荐系统领域,为了衡量两个字符串之间的相似性,通常会采用多种算法,其中余弦相似度算法...
**字符串相似度算法——Levenshtein Distance(编辑距离)** 在信息技术和计算机科学领域,字符串相似度计算是一个重要的概念,特别是在文本处理、搜索引擎优化、数据校验和生物信息学等多个场景中。Levenshtein ...
Java字符串相似度算法是用于衡量两个字符串之间相似程度的一种计算方法。在文本处理、信息检索、数据清洗等领域中,这种算法具有重要的应用价值。这里主要介绍了一种基于Levenshtein距离的Java实现。 Levenshtein...
### MySQL 计算字符串相似度 #### 背景与需求 在许多应用场景中,我们需要对两个字符串进行相似度比较,比如搜索引擎中的关键词匹配、文本分析中的近义词识别等。MySQL 提供了多种方法来实现字符串相似度的计算,...
总之,Delphi提供了丰富的工具和功能来处理字符串相似度计算,开发者可以根据具体需求选择合适的算法并进行实现。在实际项目中,理解和运用这些算法可以帮助我们更好地理解和比较文本数据,提升应用程序的功能和用户...
本篇文章将深入探讨如何使用DELPHI编程语言实现LCS(最长公共子序列)算法来衡量两个字符串的相似度。LCS算法是一种找出两个序列中最长的相同子序列的算法,它不考虑子序列的顺序,对于字符串而言,就是找到最长的...
java 计算字符串相似度
本文将深入探讨字符串相似度比较的概念、常用算法以及在JavaScript中的实现,同时关注潜在的性能和内存管理问题。 字符串相似度比较旨在量化两个或多个字符串之间的相似程度,通常以百分比形式表示。这种比较不仅...
用途:可用于论文抄袭检测、DNA等。...算法实现思路:通过对一个字符串插入、删除、替换转变成另一个字符串所需要的步骤称为距离,计算两个字符串之间的距离,从而可以得到两个字符串之间的相似度。
在这个"LD的两字符串相似度计算.zip"压缩包中,可能包含了一个名为"readme.txt"的文件,它可能解释了如何使用这个算法或者给出了一个示例。另外,"com"可能是程序代码的组成部分,可能是一个Python、Java或其他编程...
在IT领域,字符串相似度匹配是一项重要的技术,广泛应用于数据清洗、文本检索、信息过滤、推荐系统等多个场景。本主题将深入探讨“两个字符串相似度匹配”的概念、方法及其实现。 字符串相似度匹配旨在量化两个字符...
一个实现不同字符串相似度和距离度量的库。目前实现了十几种算法(包括 Levenshtein 编辑距离和兄弟、Jaro-Winkler、最长公共子序列、余弦相似度等)。查看下面的汇总表以获取完整列表... python字符串相似度 下载 ...
总的来说,字符串相似度比较是信息技术中的基础工具,深入理解和灵活运用这些算法能帮助我们解决多种实际问题。通过“字符串相似度比较T-2021-7-1.rar”中的内容,我们可以系统学习这一领域的知识,提升处理文本数据...