Edit Distance相似度算法

本文介绍了一种衡量两个字符串相似度的方法——编辑距离算法,并通过一个具体示例详细解释了其计算过程。文章还提供了一个C++实现的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先给一个例子,两个字符串eeba和abca相似度是多少呢,edit distance是一个很好的度量,定义从字符串a变到字符串b,所需要的最少的操作步骤(插入,删除,更改)为两个字符串之间的编辑距离。

image

对于eeba,abca它们之间的编辑距离为3,可以按照上面的操作步骤(不是唯一的)将eeba变到abca,1.将e变为a 2.删除e 3.添加c 共3个步骤。

典型的动态规划问题。

image

EDIT[i,j]表示对于字符串a从1到i的子串和字符串b从1到j的字串的编辑距离。(字符串下标从1开始)

EDIT[i - 1,j] + 1表示对a 在i 位置删除delete操作

EDIT[i,j - 1] + 1 表示insert添加操作

EDIT[i-1, j - 1] + f(x[i],y[j])这里如果x[i] == y[j] 则 f(x[i],y[j]) == 0 否则 ==1

表示不变或者是modify操作。

如果需要记录编辑过程如第一幅图所示,需要用二维数组记录下动态规划过程的路径信息,即记录下前一步骤的位置索引信息。

如下图

image

image

class Solution {
public:
    int minDistance(string word1, string word2) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        int row = word1.length() + 1;
        int col = word2.length() + 1;
        
        vector<vector<int> > f(row, vector<int>(col));

        for (int i = 0; i < row; i++)
            f[i][0] = i;

        for (int i = 0; i < col; i++)
            f[0][i] = i;

        for (int i = 1; i < row; i++)
            for (int j = 1; j < col; j++){
                if (word1[i-1] == word2[j-1])
                    f[i][j] = f[i-1][j-1];
                else
                    f[i][j] = f[i-1][j-1] + 1;
                f[i][j] = min(f[i][j], min(f[i-1][j]+1, f[i][j-1]+1));
            }

        return f[row-1][col-1];
    }
};
### Java 中字符串相似度算法的实现 在 Java 中,可以通过多种方式计算字符串之间的相似度。其中最常用的是基于 **编辑距离** 的算法,例如 Levenshtein 距离算法。该算法通过计算将一个字符串转换为另一个字符串所需的最小操作数(插入、删除或替换),从而衡量两者的相似程度。 以下是使用 Levenshtein 编辑距离算法的一个具体实现: #### 实现代码 ```java public class StringSimilarity { public static double similarityRatio(String str1, String str2) { if (str1 == null || str2 == null) return 0.0; if (str1.equals(str2)) return 1.0; int edits = editDistance(str1.toLowerCase(), str2.toLowerCase()); return (1 - ((double) edits / Math.max(str1.length(), str2.length()))); } private static int editDistance(String s1, String s2) { int[] costs = new int[s2.length() + 1]; for (int i = 0; i <= s1.length(); i++) { int previousCost = i; for (int j = 0; j <= s2.length(); j++) { if (i == 0) { costs[j] = j; } else { if (j > 0) { int insertCost = costs[j - 1] + 1; int deleteCost = previousCost + 1; int replaceCost = (s1.charAt(i - 1) != s2.charAt(j - 1)) ? Integer.MAX_VALUE : previousCost; costs[j] = Math.min(Math.min(insertCost, deleteCost), replaceCost); } } } if (i > 0) { previousCost = costs[s2.length()]; } } return costs[s2.length()]; } public static void main(String[] args) { String str1 = "kitten"; String str2 = "sitting"; System.out.println("similarityRatio=" + similarityRatio(str1, str2)); } } ``` 上述代码实现了 `editDistance` 方法来计算两个字符串间的编辑距离,并进一步将其转化为相似度比率[^3]。最终的结果是一个介于 0 和 1 之间的数值,值越大表示两者越相似。 --- #### 关键概念解释 1. **编辑距离** 是指将一个字符串转换为另一个字符串所需的操作次数,这些操作包括插入、删除和替换字符[^2]。 2. **相似度比率** 可以通过对编辑距离进行标准化处理得到,通常定义为 \(1 - \frac{\text{编辑距离}}{\max(\text{字符串长度})}\)。 3. 上述代码中的 `editDistance` 函数采用了动态规划的方式逐步构建解决方案矩阵,确保高效性和准确性[^4]。 --- ### 性能优化建议 对于较长的字符串,可以考虑以下改进措施: - 设置最大允许的距离阈值,在超出此范围时提前终止计算。 - 利用启发式方法减少不必要的比较运算。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值