相近字符串的匹配--编辑距离问题

本文探讨了编辑距离问题,即如何衡量两个字符串之间的差异。通过定义更改的三种基本类型:替代、插入和删除,我们可以计算字符串之间的编辑距离。借助动态规划(DP)思想,可以简化解决此类问题的算法。递归形式的编辑距离问题中,通过比较不同操作的代价,如删除、插入和替换,可以得到最小编辑距离。文章提供了递归算法的出口条件,并指出在实现时的巧妙之处。

首先需要解决的问题是:定义一个函数(cost function)计算两个字符串的相差程度。
一个合理的设计是:计算从一个字符串改成另一个字符串需要经过的步数。

更改的三种基本类型
  • 替代:更改一个字符,如shot->spot
  • 插入: 插入一个字符,如ago->agog
  • 删除:删除一个字符,如hour->our

这样计算出从字符串P变到字符串T总共需要多少基本类型,就是编辑距离。

这种相似字符串的匹配算法似乎很难,但是借助DP思想,问题将非常简洁。又是见证奇迹的时候。

递归形式的编辑距离问题

i,j 为字符串前缀子串的最后一个字符。
字符串P(长度为m)变T(长度为n),我们以 Pi,Tj 表示下标分别为 i,j 的字符。
定义一个函数D[i,j]表示前缀子串的编辑距离。
P:[1…i] 1 < i < m
T:[1…j] 1< j < n

总共三种方式右对齐两个前缀字符串

  • 如果 Pi=Tj , 子问题变为D[i-1,j-1], 否则为D[i-1,j-1]+1. 意思是:如果最右的字符匹配了,递归计算子串,否则需要替换,代价设为1.

  • D[i-1,j] + 1 表示的是删除 Pi ,再计算[1…i-1]与[1…j]的编辑距离。因为 Pi Tj 不匹配,将指向P的指针前挪一位,指向T的指针不动。+1表示的代价是删除 Pi 的代价。

  • D[i,j-1]+1表示的是在 Pi 后添加一个 Tj ,指向T的指针往左移动一位。因为当前的 Tj 通过对P的插入的方式已经匹配了,接着看下一个字符与 Pi 的对比操作。

这三类操作都是面对一个字符时候的选择策略。

D[i,j] = min{D[i-1,j]+Delete( ),D[i,j-1]+Insert( ), D[i-1,j-1]+Replace( )}
Delete:删除操作
Insert:插入操作
Replace:取代操作,如果字符相同,则为0
如果用递归算法,出口:

D[0,0] = 0;
D[i,0] = i;
D[0,j] = j;

// 递归方法实现
int EditDistanceRecursion( char *X, char *Y, int m, int n )
{
    // 基本情况
    if( m == 0 && n == 0 )
        return 0;

    if( m == 0 )
        return n;

    if( n == 0 )
        return m;

    // 递归
    int left = EditDistanceRecursion(X, Y, m-1, n) + 1;
    int right = EditDistanceRecursion(X, Y, m, n-1) + 1;
    int corner = EditDistanceRecursion(X, Y, m-1, n-1) + (X[m-1] != Y[n-1]);

    return Minimum(left, right, corner);
}

假设三个操作的代价都是1,则上面的算法是递归的算法实现。

比较值得注意的巧妙之处是用(X[m-1] != Y[n-1])来表示0,或者1,比单独比较实现代码简洁得多。

参考:http://www.acmerblog.com/dp5-edit-distance-4883.html
笔记主要来自:《算法设计手册》阅读

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值