深入理解编辑距离:从原理到实现

什么是 Levenshtein 距离?

Levenshtein 距离 是一种衡量两个字符串之间相似度的指标,它主要考量的是将一个字符串转换为另一个字符串所需要的插入、删除和替换操作的次数。

Levenshtein 距离涉及的操作主要有:

  • 插入: 向字符串 A 中添加一个字符。
  • 删除: 从字符串 A 中移除一个字符。
  • 替换: 将字符串 A 中的一个字符替换成另一个字符。

> 让我们来看一个例子,假设我们有两个字符串,字符串 A: "kitten" 需要转换为字符串 B: "sitting"。我们需要计算出所需的最少操作次数。

>

> – kitten → sitten (将 "k" 替换为 "s")

> – sitten → sittin (将 "e" 替换为 "i")

> – sittin → sitting (在末尾插入 "g")

>

> 在这个例子中,我们一共进行了三次操作,因此这两个字符串之间的 Levenshtein 距离为 3。

  • 上下界: 当且仅当两个字符串完全相同时,Levenshtein 距离为零(非负数)。对于长度分别为 m 和 n 的两个字符串,由于完全转换需要通过插入或删除来完成,它们之间最可能的 Levenshtein 距离最大值为 max(m, n)。

Levenshtein 距离的应用场景:

Levenshtein 距离在许多领域都有广泛的应用,例如:

  • 自动纠错算法: 文本编辑器和各种即时通讯应用(如 Gboard、SwiftKey 键盘等)都会在其自动纠错功能中使用 Levenshtein 距离。
  • 数据清洗: 在数据清洗和标准化任务中,它被广泛用于减少数据冗余,并识别数据挖掘过程中的相似记录。
  • 数据聚类与分类: 在聚类任务中,用于识别相似记录并将其分组;而在分类任务中,则用于识别相似记录并为其打上类别标签。

与其他编辑距离度量的关系:

让我们看看 Levenshtein 距离与其他距离度量有何不同:

  • Damerau-Levenshtein 距离: 它与 Levenshtein 距离非常相似,但它增加了一个额外的操作——相邻字符交换,使得总操作数变成了 4 种。
  • 汉明距离: 它只能应用于长度相同的字符串,用于衡量对应位置上不同字符的数量。

接下来,让我们看看如何通过不同的方法来实现它:

1) 使用递归方法计算 Levenshtein 距离

> 为了计算 Levenshtein 距离,在递归技术中,我们将使用一个简单的递归函数。它会逐一检查两个字符串中的每个字符,并递归地执行插入、删除和替换操作。

下面是上述思路的具体实现:

#### C++ 实现

// C++ code for the above approach:
#include 
using namespace std;

int levenshteinRecursive(const string& str1,
                        const string& str2, int m, int n)
{

    // str1 is empty
    if (m == 0) {
        return n;
    }
    // str2 is empty
    if (n == 0) {
        return m;
    }

    if (str1[m - 1] == str2[n - 1]) {
        return levenshteinRecursive(str1, str2, m - 1,
                                    n - 1);
    }

    return 1
        + min({
            // Insert
            levenshteinRecursive(str1, str2, m, n - 1),
            // Remove
            levenshteinRecursive(str1, str2, m - 1, n),
            // Replace
            levenshteinRecursive(str1, str2, m - 1, n - 1)
        });
}

// Drivers code
int main()
{
    string str1 = "kitten";
    string str2 = "sitting";

    // Function Call
    int distance = levenshteinRecursive(
        str1, str2, str1.length(), str2.length());
    cout << "Levenshtein Distance: " << distance << endl;
    return 0;
}

#### Java 实现

import java.io.*;

public class Solution {

    public static int levenshteinRecursive(String str1, 
                                           String str2, int m, int n) {
        // str1 is empty
        if (m == 0) {
            return n;
        }
         
        // str2 is empty
        if (n == 0) {
            return m;
        }
        if (str1.charAt(m - 1) == str2.charAt(n - 1)) {
            return levenshteinRecursive(str1, str2, m - 1, n - 1);
        }
        return 1 + Math.min(
            // Insert
            levenshteinRecursive(str1, str2, m, n - 1),
            Math.min(
                // Remove
                levenshteinRecursive(str1, str2, m - 1, n),
                
                // Replace
                levenshteinRecursive(str1, str2, m - 1, n - 1)
            )
        );
    }

    public static void main(String[] args) {
        String str1 = "kitten";
        String str2 = "sitting";

        int distance = levenshteinRecursive(str1, str2, str1.length(), str2.length());
        System.out.println("Levenshtein Distance: " + distance);
    }
}
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。如需转载,请注明文章出处豆丁博客和来源网址。https://shluqu.cn/48321.html
点赞
0.00 平均评分 (0% 分数) - 0