[C++][Leetcode][动态规划]编辑距离

编辑距离算是一个比较经典的问题,可以用于常见的拼写纠错。

1.Leetcode 72编辑距离

  • 题目描述
给定两个单词 word1 和 word2,计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
示例 1:

输入: word1 = "horse", word2 = "ros"
输出: 3
解释: 
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2:

输入: word1 = "intention", word2 = "execution"
输出: 5
解释: 
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/edit-distance
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
  • 思路分析

对于两个字符串,我们从右到左进行比较:

当a[i]==b[i]那么我们需要做任何操作,操作次数和a[i-1]与b[i-1]的操作次数相同。

如果不相等,那么我们有三种选择:第一种,删除a的当前元素(操作次数1)+以a[i-1]结尾串和以b[i]结尾串的操作次数;第二种,在当前位置插入一个元素,使得其与b[i]相等(操作次数1)+以a[i]结尾串与以b[i-1]结尾串的操作次数;第三种情况,替换a[i]使其等于b[i](操作次数1)+以a[i-1]结尾串和以b[i-1]结尾串的操作次数。在这三种情况里,选择一个操作次数最少的。

当其中一个串空是,最短的操作次数就是另外一个串的长度。

  • 代码设计
    • 递归版本
class Solution {
public:
    //递归超时
    int MinDistance(string word1,string word2,int w1,int w2)
    {
        if(w1==0)
            return w2;
        else if(w2==0)
            return w1;
        else if(word1[w1-1]==word2[w2-1])
            return MinDistance(word1,word2,w1-1,w2-1);
        
            return 1+min(MinDistance(word1,word2,w1,w2-1),min(MinDistance(word1,word2,w1-1,w2),MinDistance(word1,word2,w1-1,w2-1)));
    }
    int minDistance(string word1, string word2) {
        int w1=word1.size();
        int w2=word2.size();
        return MinDistance(word1,word2,w1,w2);
        
        
        
    }
};
  • 动态规划版本(时间复杂度N^2,空间复杂度N^2)
class Solution {
public:
    //N*N的空间 N*N的时间复杂度
    
    int minDistance(string word1, string word2) {
        int w1=word1.size();
        int w2=word2.size();
        
        vector>dp(w1+1,vector(w2+1,0));

        //dp[i][j]:表示长度为i的字符串1与长度为j的字符串2需要的操作次数

        for(int i=0;i<=w1;++i)
        {
            for(int j=0;j<=w2;++j)
            {
                if(j==0)//如果str2为空串 把str1全部删除
                    dp[i][j]=i;
                else if(i==0)//同理s1为空串
                    dp[i][j]=j;
                else if(word1[i-1]==word2[j-1])
                    dp[i][j]=dp[i-1][j-1];
                else
                {
                    dp[i][j]=1+min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1]));
                }
            }
        }

        return dp[w1][w2];
        
        
    }
};
  • 动态规划改进版本(时间复杂度N^2空间复杂度N)
class Solution {
public:
    //N*N的空间 N*N的时间复杂度
    
    int minDistance(string word1, string word2) {
        int w1=word1.size();
        int w2=word2.size();
        
        vector>dp(2,vector(w1+1,0));
        //其实可以发现我们每次更新的时候 状态只和其前一行有关系 

        //我们以str1作为基准 来比如
        for(int i=0;i<=w1;++i)
        {
            dp[0][i]=i;//假设str2为空
        }

        //i%2的作用就是取交替下标0,1
        for(int i=1;i<=w2;++i)
        {
            for(int j=0;j<=w1;++j)
            {
                if(j==0)//如果str1为空 i%2=0去当前位置p[0]
                    dp[i%2][j]=i;
                else if(word1[j-1]==word2[i-1])
                    dp[i%2][j]=dp[(i-1)%2][j-1];//和i-1,j-1一样 
                else
                {
                    dp[i%2][j]=1+min(dp[(i-1)%2][j],min(dp[i%2][j-1],dp[(i-1)%2][j-1]));
                }
            }
        }
        return dp[w2%2][w1];

        
       
        
        
    }
};

 

你可能感兴趣的:(C++程序设计)