線性dp:編輯距離

Tomorrowland_D發表於2024-08-23

編輯距離

  • 本題與力扣72.編輯距離題意一樣,閱讀完本文可以嘗試leetcode72.
    力扣題目連結

題目敘述

輸入兩個字串a,b。輸出從字串a修改到字串b時的編輯距離

輸入

NOTV
LOVER

輸出

4

題目解釋:

img

動態規劃思路

  • 這個問題顯然是一個最優解問題,我們可以考慮動態規劃的思路,那麼我們使用動態規劃的思路,要想得到最優解問題,那麼我們必須要先考慮子問題。
  • 子問題:我們先考慮a[1,2...i]b[1,2....j]的編輯距離

狀態變數的含義

  • 設立一個dp陣列,作為我們的狀態變數
    • dp[i][j]表示以從a[1...i]b[1....j]的編輯距離

遞推公式

  • 設立完狀態變數,那麼我們就進入了遞推公式的推導
    • 1.若a[i]=b[j],那麼dp[i][j]==dp[i-1][j-1]
    • 2.a[i]!=b[j]

img

  • 那麼我們就很容易的推出我們的遞推公式:
    • dp[i][j]=dp[i-1][j-1]a[i]==b[j]
    • dp[i][j]=min(dp[i-1][j-1],dp[i][j-1],dp[i-1][j])+1)(a[i]!=b[j]

遍歷順序

  • 顯然是從上到下,從左到右。

初始化dp陣列

  • 邊界條件:

    • f[i][0]=i
    • f[0][j]=j
  • 對應的初始化程式碼如下:

m=strlen(a);
n=strlen(b);
for(int i=1;i<=m;j++) dp[i][0]=i;
for(int j=1;j<=n;j++) dp[0][j]=j;
for(int i=1;i<=m;i++){
    for(int j=1;j<=n;j++){
        if(a[i-1]==b[j-1]) dp[i][j]=dp[i-1][j-1];
        else dp[i][j]=min(dp[i-1][j-1],min(dp[i][j-1],dp[i-1][j])+1;
    }
}
cout<<f[m][n];

舉例列印dp陣列

  • 舉例如下:

img

程式碼

  • 最終實現程式碼如下:
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

char a[2005],b[2005];
int f[2005][2005];

int main(){
  scanf("%s %s",a,b);
  int la=strlen(a), lb=strlen(b);
  for(int i=1;i<=la;i++) f[i][0]=i;
  for(int i=1;i<=lb;i++) f[0][i]=i
      
  for(int i=1;i<=la;i++)
    for(int j=1;j<=lb;j++)
      if(a[i-1]==b[j-1])f[i][j]=f[i-1][j-1];
      else f[i][j]=min(min(f[i-1][j],f[i][j-1]),f[i-1][j-1])+1;

  printf("%d\n",f[la][lb]);
}

相關文章