1. 程式人生 > 其它 >最小編輯代價(編輯距離問題改進版)

最小編輯代價(編輯距離問題改進版)

題目描述

給定兩個字串str1和str2,再給定三個整數ic,dc,rc,分別代表插入、刪除、替換一個字元的代價,返回將str1編輯成str2的最小代價。

該題是基於經典動態規劃問題編輯距離的改進版編輯距離問題

輸入輸出樣例

輸入1

str1=“abc” str2=“adc” ic=5 dc=3 rc=2

從"abc"編輯到"adc"把b替換成d代價最小,為2;
輸出1

2

輸入2

str1=“abc” str2=“adc” ic=5 dc=3 rc=10

從"abc"編輯到"adc",先刪除b再插入d代價最小,為8;

輸出2

8

思路解析

動態規劃問題大多都是求最值問題,求最值意味著要先窮舉才能求最值。

約定

約定DP表即二維陣列A[i][j],表示由字串A的前i位變成字串B的前j位,所形成的兩個字串變換所需要的最小編輯距離。

初始化

如果兩個字串中有一個字串是空,那麼另外一個字串變成它需要插入操作即可。

for(i=0;i<=s1.length();i++)
{
    a[i][0] = i*ic;
}
for(j=0;j<=s2.length();j++)
{
    a[0][j] = j*ic;
}

狀態轉移方程

出了上述初始化部分,我們要考慮四種情況:
1.如果字串S1和S2的末尾字元相同,即S1[i-1]==S2[j-1]

,那麼代表《前i個與前j個組成的字串代價》與《前i-1和前j-1個組成的字串代價 》是相同的。
2.如果末尾不相同,那麼就意味著需要進行變換,可以由不同的情況通過插入、刪除、替換三種操作來實現,而題目要求找最小代價,那麼求這三種對應的最小操作就行。

  • 替換:a[i-1][j-1]+uc
  • 插入/刪除(插入或刪除都可以): a[i-1][j]+dc,a[i][j-1]+ic

C++ 實現

#include <iostream>
#include <bits/stdc++.h>
using namespace std;
void printDP(int a[100][100],int q,int
p) { int i,j; for(i=0;i<q;i++) { for(j=0;j<p;j++) { cout<<a[i][j]<<" "; } cout<<endl; } } // DP表要當代價的 int minPrice(string s1,string s2,int ic,int dc,int uc) { // i j 代表兩個字串的前n個字元比對 int a[100][100]; int i,j; // base case 插入所需代價 for(i=0;i<=s1.length();i++) { a[i][0] = i*ic; } for(j=0;j<=s2.length();j++) { a[0][j] = j*ic; } // 都不是空串的情況 for(int i=1;i<=s1.length();i++) { for(int j=1;j<=s2.length();j++) { // 若末尾兩字元相同 if(s1[i-1]==s2[j-1]) { // 不需要進行任何操作,即前i個與前j個組成的字串與前i-1和前j-1個組成的字串代價是相同的 a[i][j]==a[i-1][j-1]; }else{ // 進行插入刪除編輯 a[i][j]=min(a[i-1][j-1]+uc,min(a[i-1][j]+dc,a[i][j-1]+ic)); } } } printDP(a,s1.length(),s2.length()); return a[s1.length()-1][s2.length()-1]; } int main() { cout<<minPrice("abc","adc",5,3,10); return 0; }

在這裡插入圖片描述
在這裡插入圖片描述