C++编辑距离(动态规划)

题目描述:

给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。

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

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

编辑距离:是指两个字符串之间,由一个转成另一个所需的最少编辑操作次数。
问题:word1到word2的编辑距离
子问题:word1前i个字符到word2前j个字符的编辑距离
假如有两个字符串"hat"和"wtct"
每个格子表示word1前i个字符到word2前j个字符的编辑距离

i表示插入操作,d表示删除操作,r表示替换操作。

第一行w可以由空字符串“”插入一个w得到,操作一次;wh可以由“”插入w再插入h得到,插入两次,依次得到“”到whct的操作次数。

第一列由h变为“”可以对h进行一次删除操作,由ha变为“”可以先删除h再删除a,操作两次;由hat变为“”可以进行三次删除操作依次删除三个字母。

F(1, 1)表示由h变为w的编辑距离:

由h到w,可以先在h前面插入一个w,变为wh,再把h删除,操作两次,即用F(0, 2)的状态下再加一次删除操作。
还可以先把h删除,再插入一个w,操作两次,即用F(1, 0)的状态再加一次插入操作。
还可以把h替换成w,操作一次,可以用F(0, 0)的状态加一次替换操作表示。
这三种操作都能将h变为w,而我们需要的是最少的操作次数,所以选择替换。F(1,1) 就为1。

F(1, 2)表示h变为wh的编辑距离:

由h到wh,可以先在h的前面进行两次插入操作插入wh,再将原来的h删除,即可以用F(0, 2)的状态加一次删除操作。
还可以把h先替换成w,然后再插入h,即F(1, 1)的状态再加一次插入操作。
还可以再h的前面直接插入w,即F(0, 1)的状态,由于字符h和wh的第二个字符相同,所以不需要再进行替换操作,用F(0, 1)的状态就可以表示F(1, 2)。
在这三种操作中,删除操作是2+1为3,插入操作为1+1为2,不需要替换用F(0, 1)表示为1,。所以F(1, 2)为1。

F(2, 1)表示ha变为w的编辑距离:

由ha变为w,可以先将h变为w,再把a删除,即用F(1, 1)的状态再加一次删除操作。
还可以将ha变为"",再插入w,即用F(2, 0)再加一次插入操作。
还可以将h删除,将a替换成w,即用F(1, 0)的状态加一次替换操作。
删除要两次,插入要三次,替换要两次。
所以F(2, 1)为2。

F(2, 2)表示ha变为wh的编辑距离:

由ha变为wh,可以先将h变为wh,再删除a,即用F(1, 2)的状态再加一次删除操作。
还可以ha先变为w,再插入h,即F(2, 1)的状态再加一次插入操作。
还可以将h替换成w,再将a替换成h,即F(1, 1)的状态再加一次替换操作。
在这一步想要进行删除操作需要2次(F(1, 2) + 1), 进行插入操作需要
3次(F(2, 1 + 1)), 进行替换操作需要2次(F(1, 1) + 1),所以F(2, 2)为2。

经过分析可以得出状态转移方程:
word2的每一个子串都可由word1的子串进行插入,删除,替换这三种操作得到,我们需要的是操作次数最少的结果,即:
F(i, j) = min(插入,删除,替换)
F(i, j) = min(F(i, j - 1) + 1, F(i - 1, j) + 1, F(i - 1, j - 1) + (w1[i] == w2[j] ? 0 : 1))
这里需要注意的是替换操作如果word1[i]和word2[j]相等就不需要进行替换了。

代码:

class Solution {
public:
    int minDistance(string word1, string word2) {
        int row = word1.size() + 1;
        int col = word2.size() + 1;
        int dp[row][col];
        //把第一行和第一列初始化
        for(int j = 0; j < col; ++j)
        {
            dp[0][j] = j;
        }
        for(int i = 0; i < row; ++i)
        {
            dp[i][0] = i;
        }
        //依次算出上图每个格子的状态
        for(int i = 1; i < row; ++i)
        {
            for(int j = 1; j < col; ++j)
            {
                //如果两次字符相等,不需要替换操作
                //就像上图的由h-->wh
                if(word1[i - 1] == word2[j - 1])
                    dp[i][j] = dp[i - 1][j - 1];
                else
                    dp[i][j] = min(dp[i - 1][j - 1], min(dp[i - 1][j], dp[i][j - 1])) + 1;
            }
        }
        return dp[row - 1][col - 1];
    }
};

到此这篇关于C++编辑距离(动态规划)的文章就介绍到这了,更多相关C++编辑距离(动态规划)内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++动态规划之背包问题解决方法

    本文实例讲述了C++动态规划之背包问题解决方法.分享给大家供大家参考.具体分析如下: 问题描述: 背包的最大容量为W,有N件物品,每件物品重量为w,价值为p,怎样选择物品能使得背包里的物品价值最大? 输入: 10 3   (W,N) 4 5   (w,p) 6 7   (w,p) 8 9   (w,p) 实现代码: #include <stdio.h> #define THING 20 #define WEIGHT 100 int arr[THING][WEIGHT]; /* 背包容量为wei

  • C++实现LeetCode(72.编辑距离)

    [LeetCode] 72. Edit Distance 编辑距离 Given two words word1 and word2, find the minimum number of operations required to convert word1 to word2. You have the following 3 operations permitted on a word: Insert a character Delete a character Replace a char

  • c++动态规划经典算法

    目录 基本思想 重要分析问题方法 动态规划算法实例 1.台阶问题 2.从矩阵左上角走到右下角最短路径问题 3.最大子数组问题 4.最长公共子序列 基本思想 动态规划算法通常用于求解具有某种最优性质的问题.在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解.动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解.与分治法不同的是,适合于用动态规划求解的问题,经分解得到子问题往往不是互相独立的.若用分

  • C++实现LeetCode(161.一个编辑距离)

    [LeetCode] 161. One Edit Distance 一个编辑距离 Given two strings s and t, determine if they are both one edit distance apart. Note:  There are 3 possiblities to satisify one edit distance apart: Insert a character into s to get t Delete a character from s 

  • C++动态规划之最长公子序列实例

    本文实例讲述了C++动态规划之最长公子序列解决方法.分享给大家供大家参考.具体分析如下: 问题描述: 求出两个字符串中的最长公子序列的长度. 输入: csblog belong 输出: max length = 4 实现代码: #include <stdio.h> #include <string.h> int arr[200][200]; /* 表示str1的前i位和str2的前j位的最长公子序列的长度 */ int main() { char str1[100],str2[10

  • Java动态规划之编辑距离问题示例代码

    动态规划过程是:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的,所以,这种多阶段最优化决策解决问题的过程就称为动态规划. 动态规划实际上是一类题目的总称,并不是指某个固定的算法.动态规划的意义就是通过采用递推(或者分而治之)的策略,通过解决大问题的子问题从而解决整体的做法.动态规划的核心思想是巧妙的将问题拆分成多个子问题,通过计算子问题而得到整体问题的解.而子问题又可以拆分成更多的子问题,从而用类似递推迭代的方法解决要求的问题.问题描述: 对于序列S和T,

  • C++编辑距离(动态规划)

    题目描述: 给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 . 我们可以对一个单词进行如下三种操作: 插入一个字符 删除一个字符 替换一个字符 编辑距离:是指两个字符串之间,由一个转成另一个所需的最少编辑操作次数.问题:word1到word2的编辑距离子问题:word1前i个字符到word2前j个字符的编辑距离假如有两个字符串"hat"和"wtct"每个格子表示word1前i个字符到word2前j个字符的编

  • Python实现计算最小编辑距离

    最小编辑距离或莱文斯坦距离(Levenshtein),指由字符串A转化为字符串B的最小编辑次数.允许的编辑操作有:删除,插入,替换.具体内容可参见:维基百科-莱文斯坦距离.一般代码实现的方式都是通过动态规划算法,找出从A转化为B的每一步的最小步骤.从Google图片借来的图, Python代码实现, (其中要注意矩阵的下标从1开始,而字符串的下标从0开始): def normal_leven(str1, str2): len_str1 = len(str1) + 1 len_str2 = len

  • Python文本相似性计算之编辑距离详解

    编辑距离 编辑距离(Edit Distance),又称Levenshtein距离,是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除一个字符.一般来说,编辑距离越小,两个串的相似度越大. 例如将kitten一字转成sitting:('kitten' 和 'sitting' 的编辑距离为3) sitten (k→s) sittin (e→i) sitting (→g) Python中的Levenshtein包可以方便的计算编辑距离

  • Ruby实现的最短编辑距离计算方法

    利用动态规划算法,实现最短编辑距离的计算. 复制代码 代码如下: #encoding: utf-8 #author: xu jin #date: Nov 12, 2012 #EditDistance #to find the minimum cost by using EditDistance algorithm #example output: #  "Please input a string: " #  exponential #  "Please input the

  • PHP动态规划解决0-1背包问题实例分析

    本文实例分析了PHP动态规划解决0-1背包问题.分享给大家供大家参考.具体分析如下: 背包问题描述:一个承受最大重量为W的背包,现在有n个物品,每个物品重量为t, 每个物品的价值为v. 要使得这个背包重量最大(但不能超过W),同时又需要背包的价值最大. 思路:定义一个二维数组,一维为物品数量(表示每个物品),二维是重量(不超过最大,这里是15),下面数组a, 动态规划原理思想,max(opt(i-1,w),wi+opt(i-1,w-wi)) 当中最大值, opt(i-1,w-wi)指上一个最优解

  • C#使用动态规划解决0-1背包问题实例分析

    本文实例讲述了C#使用动态规划解决0-1背包问题的方法.分享给大家供大家参考.具体如下: // 利用动态规划解决0-1背包问题 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Knapsack_problem // 背包问题关键在于计算不超过背包的总容量的最大价值 { class Program { static void Main() { int i;

随机推荐