【编程-算法】2019-10-09 编辑距离Edit-dista

2019-10-15  本文已影响0人  Chauncey_L

0 问题介绍

给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。
你可以对一个单词进行如下三种操作:

  1. kitty->pitty,替换k->s
  2. pitty->puitty ,插入u
    3.puitty->puittys,插入s
    所以w_1->w_2的编辑距离为3.

1 数学解答

我们定义两个字符串w_1w_2,它们的长度分别是|w_1|,|w_2|w_1->w_2的编辑距离为Edis_{w_1,w_2}(i,j). 其中i和j分别表示w1和w2中前i个和前j个字符串截取,那么w_1w_2的编辑距离可以用以下数学公式描述:
Edis_{w_1,w_2}(i,j)=\begin{cases} max(i,j) \qquad \qquad \qquad \qquad \qquad \qquad \qquad \qquad \quad \qquad ,if\;min(i,j)=0\\ min\begin{cases} Edis(i-1,j)+1,\\ Edis(i,j-1)+1\\ Edis(i-1,j-1)+1,while \, w_1[i]≠w_2[j] \\ Edis(i-1,j-1)+0, while \, w_1[i]=w_2[j]\\ \end{cases} \quad ,otherwise \end{cases}
对于该数学公式描述如下:
1.Edis_{w_1,w_2}(i,j)表示的是字符串w_1w_2中前i个字符和前j个字符的编辑距离,字符串的下标index从0开始。我们求得最后的编辑距离时i=|w1|, j=|w2|,Edis_{w_1,w_2}(i,j)=Edis_{w_1,w_2}(|w_1|,|w_2|)
2.当min(i,j)=0时,证明我们截取的w1,w2(记作w_1',w_2')存在空串,此时的编辑距离就是max(i,j),也就是插入或删除w_1'内的所有内容。
3.当min(i,j)≠0时,Edis_{w_1,w_2}(i,j)为以下三个值中的最小值:
-Edis_{w_1,w_2}(i-1,j)+1,删除w_1[i].
-Edis_{w_1,w_2}(i,j-1)+1,在w_1[i+1]的位置插入w_2[j].
-Edis_{w_1,w_2}(i-1,j-1)+1,替换w_1[i]w_2[j].
-Edis_{w_1,w_2}(i-1,j-1)+0w_1[i]==w_2[j].
4.为了控制最后的Edis_{w_1,w_2}(i-1,j-1)+\,?的变化,增加辅助函数d(w_1[i]?=w_2[j])
d=\begin{cases} 1,w_1[i]≠w_2[j]\\ 0,w_1[i]=w_2[j]\\ \end{cases}
通过分析,我们很容易就发现这个算法也是由多个重叠的子问题构成的,所以我们要计划使用递归和动态规划两种算法对该问题进行解决。

2 实例演示

w_1="abc",w_2="adct"

/ 0a 1b 2c
0a
1d
2c
3t

步骤1:初始化第一行第一列
依照公式

/ 0a 1b 2c
0 1 2 3
0a 1
1d 2
2c 3
3t 4

步骤2:依照公式完全矩阵

/ 0a 1b 2c
0 1 2 3
0a 1 0 1 2
1d 2 1 1 2
2c 3 2 2 1
3t 4 3 3 2

3 代码实现(PHP)

3.1 递归实现

class Solution {

    /**
     * @param String $word1
     * @param String $word2
     * @return Integer
     */
    function minDistance($word1, $word2) {
        if (strlen($word1)==0)
            return strlen($word2);
        else if (strlen($word2)==0)
            return strlen($word1);
        else if ($word1==$word2)
            return 0;
        
        if ($word1[strlen($word1)-1]==$word2[strlen($word2)-1])
            $d=0;
        else 
            $d=1;
        
        return min($this->minDistance(substr($word1,0,strlen($word1)-1),$word2)+1,
                   $this->minDistance($word1,substr($word2,0,strlen($word2)-1))+1,
                  $this->minDistance(substr($word1,0,strlen($word1)-1),substr($word2,0,strlen($word2)-1))+$d);
    }
}
class Solution {

    /**
     * @param String $word1
     * @param String $word2
     * @return Integer
     */
    function minDistance($word1, $word2) {
        $LenOfWord1=strlen($word1);
        $LenOfWord2=strlen($word2);
        if ($LenOfWord1==0)
            return $LenOfWord2;
        else if ($LenOfWord2==0)
            return $LenOfWord1;
        else if ($word1==$word2)
            return 0;
        
        if ($word1[$LenOfWord1-1]==$word2[$LenOfWord2-1])
            $d=0;
        else 
            $d=1;
        
        return min($this->minDistance(substr($word1,0,$LenOfWord1-1),$word2)+1,
                   $this->minDistance($word1,substr($word2,0,$LenOfWord2-1))+1,
                  $this->minDistance(substr($word1,0,$LenOfWord1-1),substr($word2,0,$LenOfWord2-1))+$d);
    }
}

结果在leetcode上写完提交,测试用例发现超时了,但是我也没发现题目哪里要求了时间。把strlen的结果存储起来,收效甚微。没办法,只好尝试使用动态规划。
3.2 动态规划

上一篇 下一篇

猜你喜欢

热点阅读