日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

动态规划经典题之编辑距离

發(fā)布時(shí)間:2025/3/15 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 动态规划经典题之编辑距离 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 題目
  • 解題思路
    • (1)基本過程
    • (2)動(dòng)態(tài)規(guī)劃-遞歸
    • (3)動(dòng)態(tài)規(guī)劃-dp table
  • 代碼

題目

leetCode72:編輯距離

編輯距離算法是一個(gè)非常實(shí)用的算法,它的作用是求出把一個(gè)字符串s1變?yōu)榱硪粋€(gè)字符串s2所需要的最少的操作數(shù)
此過程中,只能對(duì)字符串進(jìn)行插入、刪除或替換(其實(shí)還有一種隱形操作,就是略過)

比如把rad變?yōu)閍pple,就需要經(jīng)過5步

解題思路

(1)基本過程

對(duì)于字符串類的題目,一般都會(huì)使用到兩個(gè)指針,這里面也不例外。上面的動(dòng)圖中,展現(xiàn)的正是兩個(gè)指針i和j分別從后向前掃描兩個(gè)字符串。
在這個(gè)過程中如果j走完了,i還沒有走完的話,那么就需要把s1刪除,縮短為s2單

如果i走完了,但j沒有走完,那么就想要把s2中的插入到s1中

(2)動(dòng)態(tài)規(guī)劃-遞歸

使用動(dòng)態(tài)規(guī)劃解題,一定要考慮題目的狀態(tài)和選擇是什么?

  • 狀態(tài):這里顯然是i和j指針的位置
  • 選擇:所選的操作,加上跳過,共有四種操作(skip,insert,delete,replace)
if s1[i]==s2[j]skip; elseinsert or delete or relace;

還有“base case”,也就是最簡(jiǎn)單的情況是什么呢?這里其實(shí)就是上面所敘述的那兩種情況

首先采用遞歸解法說明。定義一個(gè)dp遞歸函數(shù),函數(shù)形參分別就是i和j,該函數(shù)的返回值就是s1[0....i]和s2[0...j]的最小編輯距離,最終一步一步遞歸,可以得到問題的最終答案。

現(xiàn)在看該函數(shù)的base case,也就是如果j走完了,就把i刪除了;如果i走完了,就把j剩下的全部插入

int dp(i,j) {if i==-1return j+1;if j==-1return i+1; }

如果遇到的字符相等,那么就什么也不做,直接跳過。也即是說s1[0....i]和s2[0....j]的最小編輯距離實(shí)際就是s1[0...i-1]和s2[0....j-1]的最小編輯距離。

int dp(i,j) {if i==-1return j+1;if j==-1return i+1;if(s1[i]==s[j])return dp[i-1][j-1];else}

如果遇到的字符不相等,那么我們就需要進(jìn)行選擇三種操作了。需要注意的是三種操作是肯定存在重疊問題,這也是遞歸不可避免的問題,因?yàn)橐粋€(gè)字符變成另一個(gè)字符除了可以替換外,我也可以直接插入一個(gè)。

  • 第一種操作:插入;遞歸函數(shù)為dp(i,j-1)+1。如果選擇了這種操作,那么就會(huì)直接在s1[i]中插入一個(gè)和s2[j]一樣的字符,此時(shí)s2[j]會(huì)被匹配到。注意操作數(shù)+1

  • 第二種操作:刪除;遞歸函數(shù)為dp(i-1,j)+1。如果選擇了這種操作,那么就會(huì)直接把s[i]這個(gè)字符刪除掉。

  • 第三種操作:替換;遞歸函數(shù)為dp(i-1,j-1)+1。如果選擇了這種操作就會(huì)直接把s1[i]替換為s2[j]。

于是偽代碼如下

int dp(i,j) {if i==-1return j+1;if j==-1return i+1;if(s1[i]==s[j])return dp[i-1][j-1];elsereturn min(dp(i,j-1)+1;//插入dp(i-1,j)+1;//刪除dp(i-1,j-1)+1;//替換) }

還是那句話,這種解法一定存在大量重疊子問題。比如能過替換得到的結(jié)果也可以通過刪除后插入完成,這就是一條重復(fù)路徑,如果發(fā)現(xiàn)了一定重復(fù)問題,那么一定會(huì)有千千萬萬個(gè)重復(fù)問題,就像斐波那契數(shù)列一樣。而重疊子問題是可以通過備忘錄解決的

memo=dict(); int dp(i,j) {if((i,j) in memo)return memo[(i,j)];if i==-1return j+1;if j==-1return i+1;if(s1[i]==s[j])return dp[i-1][j-1];elsereturn min(dp(i,j-1)+1;//插入dp(i-1,j)+1;//刪除dp(i-1,j-1)+1;//替換) }

(3)動(dòng)態(tài)規(guī)劃-dp table

遞歸便于說明問題的解決思路,實(shí)際寫代碼時(shí)我們一般采用的還是自底向上的解法,也就是動(dòng)態(tài)規(guī)劃數(shù)組。有了上面的基礎(chǔ),我們很容易能夠理解,和公共子串,子序列那些題一樣**,這道題的數(shù)組也一定是一個(gè)二維數(shù)組**


其中dp[…][0]和dp[0][…]對(duì)應(yīng)的就是base case(也即是把rad變成空串,那么需要3步),dp[i][j]存儲(chǔ)的是s1[0…i-1]和s2[0…j-1]的最小編輯距離。(dp函數(shù)的base case是i和j為-1,但是數(shù)組索引至少為0,所以要偏移1位)

代碼

class Solution { public:int minDistance(string word1, string word2) {int len1=word1.size();int len2=word2.size();vector<vector<int>> dp(len1+1,vector<int>(len2+1,0));//dp數(shù)組for(int i=1;i<=len1;i++)//base casedp[i][0]=i;for(int j=1;j<=len2;j++)dp[0][j]=j;for(int i=1;i<=len1;i++){for(int j=1;j<=len2;j++){if(word1[i-1]==word2[j-1])dp[i][j]=dp[i-1][j-1];elsedp[i][j]=min//min函數(shù)只有兩個(gè)形參,所以這樣寫(dp[i-1][j]+1,//插入min(dp[i][j-1]+1,//刪除dp[i-1][j-1]+1)//替換);}}return dp[len1][len2];} };

總結(jié)

以上是生活随笔為你收集整理的动态规划经典题之编辑距离的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。