编辑距离(DP)

作者: KyoDante | 来源:发表于2020-10-16 10:30 被阅读0次

让我们来看看编辑距离在WIKI是怎么说的:

There are other popular measures of edit distance, which are calculated using a different set of allowable edit operations. For instance,

以上涵盖了多种编辑距离,但是允许的操作不一样,以增、删、替换为例,则需要使用Levenshtein distance(体现在很多类似一次编辑的编程题中)。其余几种距离,比如:Jaro distance,以后有机会继续学习。


问题的开始:假定以L(i,j)当作串a的前 i个字符和串b的前 j个字符的L氏编辑距离。

首先,是考虑初始值,L(0,j) 代表空串和前j个字符,则对串a作j次增或者对串b作j次删,即可完成串间转换,此时距离为j

其次,是对三种可能情况构成(涵盖增、删、替换),取最小值:

  1. (替换) 分别考虑前i-1,j-1个字符,那么当前的ij只需要看是否不相等,不相等就完成替换; 即:L(i,j) = L(i-1,j-1) + 1_{(如果a[i] = b[j])}
  2. (增/删) 分别考虑前i-1,j个字符,分两种情况:
  • 2.1. 考虑从串a的i-1个字符转串b的j字符,此时,则相当于是删除了串a的第i个字符,然后将串a剩余部分转换成串b;
  • 2.2. 考虑从串b的j个字符转串a的i-1个字符,此时,则相当于在串b末尾增加了串a的第i个字符,然后将原串b转换成串a的前i-1个字符。
  • 2.0. 以上两种情况是对称的形式,整合,得L(i,j) = L(i-1,j) + 1
  1. (增/删) 和第2点同理。整合,得L(i,j) = L(i,j-1) + 1

最终,得到递推公式:
\begin{aligned} L(i,j) = \begin{cases} max(i,j) ; 如果 min(i,j) = 0 \\ min \begin{cases} L(i,j) = L(i-1,j-1) + 1_{(如果a[i] = b[j])} \\ L(i,j) = L(i-1,j) + 1 \\ L(i,j) = L(i,j-1) + 1 \\ \end{cases} \end{cases} \end{aligned}

根据递推公式,就可以写基础版的程序:


此处以LeetCode的 面试题 01.05. 一次编辑 作为例子,仅供参考:

题目:字符串有三种编辑操作:插入一个字符、删除一个字符或者替换一个字符。 给定两个字符串,编写一个函数判定它们是否只需要一次(或者零次)编辑。

示例 1:
输入:
first = "pale"
second = "ple"
输出: True
示例 2:
输入:
first = "pales"
second = "pal"
输出: False

class Solution {
public:
    bool oneEditAway(string first, string second) {
        // 建表
        int first_len = first.length();
        int second_len = second.length();
        int ** table = new int* [first_len+1];
        // 初始化
        for(int i = 0;i<= first_len; i++)
        {
            table[i] = new int[second_len+1]();
        }
        // 空串情况(对应1.)
        for(int i = 1;i<= first_len; i++)
        {
            table[i][0] = i;
        }
        for(int j = 1;j<= second_len;j++)
        {
            table[0][j] = j;
        }
        // 非空串的dp(对应2.和3.)
        for(int i = 1;i<= first_len; i++)
        {
            for(int j = 1;j<= second_len;j++)
            {
                int d1 = table[i-1][j-1];
                if (first[i-1] != second[j-1])
                {
                    d1 += 1;
                }
                int d2 = table[i-1][j] + 1;
                int d3 = table[i][j-1] + 1;
                table[i][j] = d1 > d2 ? (d3 > d2 ? d2 : d3) : (d3 > d1 ? d1 : d3);
            }   
        }

        return (table[first_len][second_len] <= 1) ? true : false;
    }
};
提交时间 提交结果 运行时间 内存消耗 语言
2 天前 通过 12 ms 8.6 MB C++

如何优化?或者有其他更加巧妙的解法?希望不吝赐教。

相关文章

  • 编辑距离(DP)

    让我们来看看编辑距离在WIKI是怎么说的: There are other popular measures of...

  • 动态规划(dp)-最短编辑距离

    应该是我接触的第一个动态规划的算法,可以说是很经典了,Levenstein 距离。 问题描述 设A和B是2个字符串...

  • [DP] 2种编辑距离(Damerau/Levenshtein

    做完这题觉得必须得来个解题报告了,这题的动态规划有点酸爽啊~ 问题如下: L氏距离(Levenshtein Dis...

  • 44. 通配符匹配

    44. 通配符匹配 字符串dp 类似的还有经典的72. 编辑距离本题是10. 正则表达式匹配的稍简单版本 dp[i...

  • DP 递归 递归 + 缓存

    最近发现DP的本质就是递归 + 缓存占坑 后续补经典的例子 爬楼梯 最小编辑距离 ... naive 递归 递归 ...

  • 10. 正则表达式匹配

    10. 正则表达式匹配 字符串dp 类似的还有经典的72. 编辑距离dp[i][j]表示以前i-1个s和前j-1个...

  • 72. Edit Distance [Hard] 编辑距离DP

  • leetcode

    72、最小编辑距离 动态规划: dp[i][j]代表 word1 到 i 位置转换成word2 到 j 位置需要最...

  • 编辑距离

    为什么不同操作就是对应与d的左移上移或左上移?这个问题递归角度较易理解。DP角度,d记录的是目前最小编辑距离。左、...

  • 编辑距离及编辑距离算法

    无意间看到了有人问编辑距离算法,当时对这个概念很陌生,也就去学习了下,做下总结,记录下,好记性不如烂笔头。 编辑距...

网友评论

    本文标题:编辑距离(DP)

    本文链接:https://www.haomeiwen.com/subject/bmlwpktx.html