00_解读《算法的乐趣》--计算两个字符串的编辑距离

重要提示: 请结合王晓华老师的《算法的乐趣》章节3.3动态规划阅读此文

本文是笔者对书中章节的小小解读, 仅记录下来防止遗忘;

实际应用场景:

搜索引擎根据你输错的字符, 推荐给你正确的结果:
“Juyl” –> “July”

一. 例子: “SNOWY” –转换–> “SUNNY”

书中提到,
转换方法1(对比顺序是正向: S(头) --> Y(尾)):

S - N O W Y
S U N N - Y
转换代价: cost = 3 (插入U, 替换O, 删除W)

转换方法2(对比顺序是逆向: Y(尾) --> S(头)):

- S N O W - Y
S U N - - N Y
转换代价: cost = 5 (插入S, 替换S, 删除O, 删除W, 插入N)

二. 动态规划内涵及步骤

  1. 定义最优子问题
  2. 定义状态
  3. 定义决策状态转换方程(本人认为决策就是状态转换方程)
  4. 确定边界条件

总结:
我认为动态规划更像一种”思想”而不是一种”方法”;
上面4个步骤, 根据思考的角度不同, 得出的结论也不同; 所以更类似一种指导思想;
后文中的一种形容更像是方法: 动态规划 = 递推 + 备忘录;

三. 几种解法

1. 朴素的递归解法:
int EditDistance(char *src, char *dest) {
    if ((strlen(src) == 0 || strlen(dest) == 0))
        return abs(strlen(src) - strlen(dest));

    if ((src[0] == dest[0]))
        return EditDistance(src + 1, dest + 1);

    int edIns = EditDistance(src, dest + 1);    // source插入字符
    int edDel = EditDistance(src + 1, dest);    // source删除字符
    int edRep = EditDistance(src + 1, dest + 1);    // source替换字符

    return min(min(edIns, edDel), edRep) + 1;
}

乍一看, 我对朴素的递归算法时间复杂度是O(3^n)这句话一脸懵逼,
心想, 是怎么得出这样的时间复杂度的呢??
其实从概率论的角度来思考的话,
对应到我们的例子,
1. SNOWYSUNNY总共有5对字符, SS, NU, ON, WN, YY;
2. 每一对字符, 都有3种操作, 分别是增/删/改;
3. 题目要求是找出最小的值, 那么肯定需要遍历所有可能性;

所有的可能性有: 3 * 3 * 3 * 3 * 3 == 3^5种; 左式如果是理解概率论的同学, 应该就很好理解了;
这种时间复杂度, 明显是不可接受的; 所以要根据动态规划的指导思想开始改造了;

2. 添加”备忘录”

作者王晓华老师根据文章中之前提到的几个步骤, 引入动态规划算法

因素实例
状态: d[i, j]从子串source[1…i]到子串target[1…j]之间的编辑距离
最优子结构子问题就变为: 将source的前[1…i]个字符转换为target的[1…m]个字符所需要的最小编辑距离是什么?

其中状态, 说说本人的理解, 对应到实例SNOWY, SUNNY;
1. SNOWY可以拆成5种: S, SN, SNO, SNOW, SNOWY
2. 同理, SUNNY拆成S, SU, SUN, SUNN, SUNNY;
3. 上述拆分满足[1...i]. [1...j]的拆分规则;
4. 总共5 * 5 = 25种状态

等待再补充…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值