java数组相似度_Java 计算两个字符串的相似度

本文探讨了一种使用动态规划解决字符串编辑距离问题的方法,通过递推公式避免了重复计算,与计算最长公共子序列类似。作者提供了C++代码实现,并分析了原有解法中的重复计算问题,以及如何通过优化得到更高效的算法。
摘要由CSDN通过智能技术生成

问题

许多程序会大量使用字符串。对于不同的字符串,我们希望能够有办法判断其相似程度。我们定义了一套操作方法来把两个不相同的字符串变得相同,具体的操作方法为:

1.修改一个字符(如把“a”替换为“b”)。

2.增加一个字符(如把“abdd”变为“aebdd”)。

3.删除一个字符(如把“travelling”变为“traveling”)。

比如,对于“abcdefg”和“abcdef”两个字符串来说,我们认为可以通过增加/减少一个“g“的方式来达到目的。上面的两种方案,都仅需要一次操作。把这个操作所需要的次数定义为两个字符串的距离,给定任意两个字符串,你是否能写出一个算法来计算出它们的距离?

分析与解法

不难看出,两个字符串的距离肯定不超过它们的长度之和(我们可以通过删除操作把两个串都转化为空串)。虽然这个结论对结果没有帮助,但至少可以知道,任意两个字符串的距离都是有限的。

我们还是应该集中考虑如何才能把这个问题转化成规模较小的同样的问题。如果有两个串A=xabcdae和B=xfdfa,它们的第一个字符是相同的,只要 计算A[2,…,7]=abcdae和B[2,…,5]=fdfa的距离就可以了。但是如果两个串的第一个字符不相同,那么可以进行如下的操作(lenA 和lenB分别是A串和B串的长度):

1.删除A串的第一个字符,然后计算A[2,…,lenA]和B[1,…,lenB]的距离。

2.删除B串的第一个字符,然后计算A[1,…,lenA]和B[2,…,lenB]的距离。

3.修改A串的第一个字符为B串的第一个字符,然后计算A[2,…,lenA]和B[2,…,lenB]的距离。

4.修改B串的第一个字符为A串的第一个字符,然后计算A[2,…,lenA]和B[2,…,lenB]的距离。

5.增加B串的第一个字符到A串的第一个字符之前,然后计算A[1,…,lenA]和B[2,…,lenB]的距离。

6.增加A串的第一个字符到B串的第一个字符之前,然后计算A[2,…,lenA]和B[1,…,lenB]的距离。

在这个题目中,我们并不在乎两个字符串变得相等之后的字符串是怎样的。所以,可以将上面6个操作合并为:

1.一步操作之后,再将A[2,…,lenA]和B[1,…,lenB]变成相同字符串。

2.一步操作之后,再将A[1,…,lenA]和B[2,…,lenB]变成相同字符串。

3.一步操作之后,再将A[2,…,lenA]和B[2,…,lenB]变成相同字符串。

这样,很快就可以完成一个递归程序。

int calStringDis(string strA, int pABegin,int pAEnd,string strB, int pBBegin,int pBEnd)

{

if (pABegin > pAEnd)

{

if (pBBegin > pBEnd)

return 0;

else

return pBEnd - pBBegin + 1;

}

if (pBBegin > pBEnd)

{

if(pABegin > pAEnd)

return 0;

else

return pAEnd - pABegin + 1;

}

if (strA[pABegin] == strB[pBBegin])

{

return calStringDis(strA,pABegin+1,pAEnd,strB,pBBegin+1,pBEnd);

}

else

{

int t1 = calStringDis(strA,pABegin+1,pAEnd,strB,pBBegin+2,pBEnd);

int t2 = calStringDis(strA,pABegin+2,pAEnd,strB,pBBegin+1,pBEnd);

int t3 = calStringDis(strA,pABegin+2,pAEnd,strB,pBBegin+2,pBEnd);

return minValue(t1,t2,t3)+1;

}

}

以上解法来自《编程之美》,有什么地方需要改进的呢?问题在于:在递归的过程中,有些数据被重复计算了。

很经典的可使用动态规划方法解决的题目,和计算两字符串的最长公共子序列相似。

设Ai为字符串A(a1a2a3 … am)的前i个字符(即为a1,a2,a3 … ai)

设Bj为字符串B(b1b2b3 … bn)的前j个字符(即为b1,b2,b3 … bj)

设 L(i,j)为使两个字符串和Ai和Bj相等的最小操作次数。

当ai==bj时 显然 L(i,j) = L(i-1,j-1)

当ai!=bj时

若将它们修改为相等,则对两个字符串至少还要操作L(i-1,j-1)次

若删除ai或在bj后添加ai,则对两个字符串至少还要操作L(i-1,j)次

若删除bj或在ai后添加bj,则对两个字符串至少还要操作L(i,j-1)次

此时L(i,j) = min( L(i-1,j-1), L(i-1,j), L(i,j-1) ) + 1

显然,L(i,0)=i,L(0,j)=j, 再利用上述的递推公式,可以直接计算出L(i,j)值。

int calculateStringDistance(string strA, string strB)

{

int lenA = (int)strA.length()+1;

int lenB = (int)strB.length()+1;

int **c = new int*[lenA];

for(int i = 0; i < lenA; i++)

c[i] = new int[lenB];

// Record the distance of all begin points of each string

//初始化方式与背包问题有点不同

for(int i = 0; i < lenA; i++) c[i][0] = i;

for(int j = 0; j < lenB; j++) c[0][j] = j;

c[0][0] = 0;

for(int i = 1; i < lenA; i++)

{

for(int j = 1; j < lenB; j++)

{

if(strB[j-1] == strA[i-1])

c[i][j] = c[i-1][j-1];

else

c[i][j] = minValue(c[i][j-1], c[i-1][j], c[i-1][j-1]) + 1;

}

}

int ret = c[lenA-1][lenB-1];

for(int i = 0; i < lenA; i++)

delete [] c[i];

delete []c;

return ret;

}

参考:

http://www.cnblogs.com/yujunyong/articles/2004724.html

http://www.cnblogs.com/flyinghearts/archive/2011/03/22/1991988.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用 Java 语言计算两个字符串相似度可以使用字符串比较算法,例如 Levenshtein 距离算法。 Levenshtein 距离算法是一种用于计算两个字符串之间的编辑距离的算法。编辑距离指的是将一个字符串转换为另一个字符串所需的最少编辑操作次数,例如插入、删除和替换。 要实现 Levenshtein 距离算法,需要定义一个函数,该函数接受两个字符串作为参数,并返回它们之间的编辑距离。这里是一个使用递归的方法来实现 Levenshtein 距离算法的示例: ``` public static int calculateLevenshteinDistance(CharSequence lhs, CharSequence rhs) { int[][] distance = new int[lhs.length() + 1][rhs.length() + 1]; for (int i = 0; i <= lhs.length(); i++) distance[i][0] = i; for (int j = 1; j <= rhs.length(); j++) distance[0][j] = j; for (int i = 1; i <= lhs.length(); i++) for (int j = 1; j <= rhs.length(); j++) distance[i][j] = minimum( distance[i - 1][j] + 1, distance[i][j - 1] + 1, distance[i - 1][j - 1] + ((lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1)); return distance[lhs.length()][rhs.length()]; } private static int minimum(int a, int b, int c) { return Math.min(Math.min(a, b), c); } ``` 调用该函数并传入两个字符串即可得到它们之间的编辑距离。要计算两个字符 ### 回答2: 在Java语言中,可以使用字符串相似度算法计算两个字符串之间的相似度。以下是一种常用的方法: 一、使用Levenshtein距离计算相似度: Levenshtein距离是通过对比两个字符串之间的差异来计算相似度的一种方法。可以通过以下步骤来实现: 1. 创建一个二维数组,大小为[m+1][n+1],其中m和n分别为两个字符串的长度。 2. 初始化数组的第一行和第一列为0到m和0到n的数字。 3. 迭代数组的每个元素,如果当前字符相同,则该位置的值等于左上角位置的值;否则,该位置的值等于左上角位置的值加1。 4. 最后,数组的右下角元素的值就是Levenshtein距离,通过1减去该值再除以较长字符串的长度,即可得到相似度。 二、使用Cosine相似度计算相似度: Cosine相似度是通过计算两个字符串之间的余弦夹角来衡量它们的相似度的一种方法。可以通过以下步骤来实现: 1. 将两个字符串分别转换成向量空间模型(Vector Space Model)的表示形式。 2. 对两个向量进行归一化处理,即将每个向量的每个分量除以该向量的模长。 3. 计算两个向量之间的内积,并除以两个向量的模长的乘积。 4. 最后,得到的结果即为两个字符串之间的Cosine相似度。 以上是使用Java语言计算两个字符串相似度的两种常见方法,根据具体需求和使用场景,选择合适的方法来进行计算。 ### 回答3: 使用Java语言可以通过计算两个字符串相似度来衡量它们之间的相似程度。以下是一种比较常见的字符串相似度计算方法——Levenshtein距离算法。 Levenshtein距离是一种编辑距离,用于度量两个字符串之间的差异。通过对两个字符串进行插入、删除和替换操作,使得两个字符串相等所需的最少操作次数即为Levenshtein距离。 我们可以使用动态规划的思想来实现Levenshtein距离的计算。定义一个二维数组dp,dp[i][j]表示将字符串s1的前i个字符转换为字符串s2的前j个字符所需要的最少操作次数。初始化时,dp[i][0] = i,dp[0][j] = j,代表将一个字符串转换为空字符串所需的操作次数。 接下来,从字符串的第一个字符开始比较,若两个字符相同,则dp[i][j] = dp[i-1][j-1];否则,dp[i][j] = min(dp[i-1][j-1], dp[i][j-1], dp[i-1][j]) + 1,分别代表替换、插入和删除操作。 最终,dp[m][n](m和n分别为两个字符串的长度)即为两个字符串的Levenshtein距离。为了得到相似度,可以计算1 - Levenshtein距离/Max(字符串1长度,字符串2长度)。 通过编写Java代码实现上述算法,我们可以方便地计算两个字符串相似度。这样可以应用于文本的相似度分析、搜索引擎关键词匹配等应用场景中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值