美文网首页
【编程-算法】2019-10-09 编辑距离Edit-dista

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

作者: Chauncey_L | 来源:发表于2019-10-15 08:53 被阅读0次

    0 问题介绍

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

    • 插入一个字符(insertion)
    • 删除一个字符(deletion)
    • 替换一个字符(Substitution)
      例如
      w1="kitty", 2="puittys". w1->w2的编辑距离如下
    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 动态规划

    相关文章

      网友评论

          本文标题:【编程-算法】2019-10-09 编辑距离Edit-dista

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