怎么用c++实现编辑距离

  介绍

这篇文章主要讲解了“怎么用c++实现编辑距离”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习”怎么用c++实现编辑距离”吧!

编辑距离编辑距离

给定两个words  word1 , 以及 word2 ,找到所需要的最小数量的操作convert  word1 ,用 word2

你有以下3个操作允许> <李>

插入一个字符

<李>

删除一个字符

<李>

替换一个字符

示例1:

输入:word1=癶orse", word2=皉os"输出:
3
解释:
马→rorse(替换& # 39;h # 39;& # 39;" # 39;)
rorse→玫瑰(移除& # 39;" # 39;)
上升→ros(移除& # 39;e # 39;)

示例2:

输入:word1=癷ntention", word2=癳xecution"
输出:5
解释:
意图→发明(移除& # 39;t # 39;)
本→enention(替换& # 39;我# 39;& # 39;e # 39;)
enention→exention(替换& # 39;n # 39;& # 39;x # 39;)
exention→exection(替换& # 39;n # 39;& # 39;c # 39;)
exection→执行(插入& # 39;u # 39;)

这道题让求从一个字符串转变到另一个字符串需要的变换步骤,共有三种变换方式,插入一个字符,删除一个字符,和替换一个字符。题目乍眼一看并不难,但是实际上却暗藏玄机,对于两个字符串的比较,一般都会考虑一下用HashMap统计字符出现的频率,但是在这道题却不可以这么做,因为字符串的顺序很重要。还有一种比较常见的错误,就是想当然的认为对于长度不同的两个字符串,长度的差值都是要用插入操作,然后再对应每位字符,不同的地方用修改操作,但是其实这样可能会多用操作,因为删除操作有时同时可以达到修改的效果,比如题目中的例子1,当把马变为rorse之后,之后只要删除第二个r,跟最后一个e,就可以变为ros。实际上只要三步就完成了,因为删除了某个字母后,原来左右不相连的字母现在就连一起了,有可能刚好组成了需要的字符串,所以在比较的时候,要尝试三种操作,因为谁也不知道当前的操作会对后面产生什么样的影响。对于当前比较的两个字符word1[我]和word2 [j],若二者相同,一切好说,直接跳到下一个位置。若不相同,有三种处理方法,首先是直接插入一个word2 [j],那么word2 [j]位置的字符就跳过了,接着比较word1[我]和word2 [j + 1]即可。第二个种方法是删除,即将word1[我]字符直接删掉,接着比较word1 (i + 1)和word2 [j]即可。第三种则是将word1[我]修改为word2 [j],接着比较word1 (i + 1)和词[j + 1]即可。分析到这里,就可以直接写出递归的代码,但是很可惜会超过时间有限,所以必须要优化时间复杂度,需要去掉大量的重复计算,这里使用记忆数组备忘录来保存计算过的状态,从而可以通过橙汁,注意这里的insertCnt, deleteCnt, replaceCnt仅仅是表示当前对应的位置分别采用了插入,删除,和替换操作,整体返回的最小距离,后面位置的还是会调用递归返回最小的,参见代码如下:

解法一:

class  Solution  {   公众:   ,,,int  minDistance (string  word1, string  word2), {   ,,,,,,,int  m =, word1.size (),, n =, word2.size ();   ,,,,,,,vector祝辞,备忘录(m, vector (n));   ,,,,,,,return 辅助(word2, word1, 0, 0),备忘录);   ,,,}   ,,,int 辅助(string&, word1, int 我,string&, word2,, int  j, vector祝辞,,备忘录),{   ,,,,,,,if (小姐:==,word1.size ()), return  (int) word2.size(),安康;j;   ,,,,,,,if  (j ==, word2.size ()), return  (int) word1.size(),神;我;   ,,,,,,,if (备忘录[我][j],祝辞,0),return 备忘录[我][j];   ,,,,,,,int  res =, 0;   ,,,,,,,if  (word1[我],==,word2 [j]), {   ,,,,,,,,,,,return 辅助(word1,小姐:+,1,word2,, j  +, 1,备忘录);   ,,,,,,,},{else    ,,,,,,,,,,,int  insertCnt =,助手(word1,,我,,word2,, j  +, 1,备忘录);   ,,,,,,,,,,,int  deleteCnt =,助手(word1,小姐:+,1,word2,, j,备忘录);   ,,,,,,,,,,,int  replaceCnt =,助手(word1,小姐:+,1,word2,, j  +, 1,备忘录);   ,,,,,,,,,,,res =, min (insertCnt, min (deleteCnt, replaceCnt)), +, 1;   ,,,,,,,}   ,,,,,,,return 备忘录[我][j],=, res;   ,,,}   };

根据以往的经验,对于字符串相关的题目且求极值的问题,十有八九都是用动态规划动态编程来解,这道题也不例外。其实解法一的递归加记忆数组的方法也可以看作是DP的递归写法。这里需要维护一个二维的数组DP,其大小为麦根,m和n分别为word1和word2的长度.dp[我][j]表示从word1的前我个字符转换到word2的前十个字符所需要的步骤。先给这个二维数组DP的第一行第一列赋值,这个很简单,因为第一行和第一列对应的总有一个字符串是空串,于是转换步骤完全是另一个字符串的长度。跟以往的DP题目类似,难点还是在于找出状态转移方程,可以举个例子来看,比如word1是“bbc", word2是“abcd",可以得到DP数组如下:

怎么用c++实现编辑距离