51nod 1183 編輯距離 dp

2021-07-29 16:13:59 字數 3552 閱讀 9974

1183 編輯距離

基準時間限制:1 秒 空間限制:131072 kb 分值: 0 

難度:基礎題

編輯距離,又稱levenshtein距離(也叫做edit distance),是指兩個字串之間,由乙個轉成另乙個所需的最少編輯操作次數。許可的編輯操作包括將乙個字元替換成另乙個字元,插入乙個字元,刪除乙個字元。

例如將kitten一字轉成sitting:

sitten (k->s)

sittin (e->i)

sitting (->g)

所以kitten和sitting的編輯距離是3。俄羅斯科學家vladimir levenshtein在2023年提出這個概念。

給出兩個字串a,b,求a和b的編輯距離。

input

第1行:字串a(a的長度 <= 1000)。

第2行:字串b(b的長度 <= 1000)。

output

輸出a和b的編輯距離
input示例

kitten

sitting

output示例 3

//遞推公式賊幾把難想啊

#include#include#includeusing namespace std;

int dp[1001][1001];

int main()

cout<

給定兩個字串s和t,對於t我們允許三種操作:

(1) 在任意位置新增任意字元

(2) 刪除存在的任意字元

(3) 修改任意字元 

問最少操作多少次可以把字串t變成s? 

例如: s=  「abcf」   t = 「dbfg」

那麼我們可以

(1) 把d改為a

(2) 刪掉g

(3) 加入c

所以答案是3。

(1) 把t中字元全刪了,再新增s的全部字元,操作次數m + n。

(2) 把t中字元刪或加成m個,再修改 操作次數最多 |n – m| + m。

雖然,我們找到了這樣的上界,bfs從實際角度並不可行,因為搜尋空間是指數的,這取決於s中的字元種類——具體的數量級不好估計。

這個問題之所以難,是難在有「新增」「刪除」這樣的操作,很麻煩。我們試試換個角度理解問題,把它看成字串對齊的問題,事實上從生物資訊學對比基因的角度,我們可以這樣理解問題。

給定字串s和t,我們可以用一種特殊字元促成兩個字串的對齊。我們加的特殊字元是「-」, 我們允許在s和t中任意新增這種特殊字元使得它長度相同,然後讓這兩個串「對齊」,最終兩個串相同位置出現了不同字元,就扣1分,我們要使得這兩個串對齊扣分盡量少。

對於例子 我們實際上採取了這樣的對齊方式:

12345

abcf-

db-fg

注意:如果要對齊,兩個「-」相對是沒有意義的,所以我們要求不出現這種情況。

那麼看一下:

(1) s,t對應位置都是普通字元,相同,則不扣分。 例如位置2,4

(2) s,t對應位置都是普通字元,不同,則扣1分。 例如位置1

(3) s在該位置是特殊字元,t在該位置是普通字元,則扣1分,例如位置5

(4) s在該位置是普通字元,t在該位置是特殊字元,則扣1分,例如位置3

我們來看看扣分專案對應什麼?

(1) 不扣分,直接對應

(2) 對應把t中對應位置的字元修改

(3) 對應在t中刪除該字元

(4) 對應在t中新增該字元

好了,目標明確,感覺像不像 lcs?我們嘗試一下:

設f(i,j)表示s的前i位和t的前j位對齊後的最少扣分。

那我們來看看最後一位,對齊的情況

(1) 必須s[i] == t[j], 這時前i – 1和j – 1位都已經對齊了,這部分肯定要最少扣分。這種情況下最少的扣分是f(i-1,j-1)

(2) 和(1)類似,s[i]≠t[j],這種情況下最少的扣分是f(i -1, j – 1) + 1

(3) s的前i位和t的前(j – 1)位已經對齊了,這部分扣分也要最少。這種情況下最少的扣分是f(i,j-1) + 1

(4) s的前(i-1)位已經和t的前j位對齊了,這部分扣分要最少。這種情況下最少的扣分是f(i,j-1) + 1

具體f(i,j)取什麼值,顯然是要看哪種情況的扣分最少。

為了方便,我們定義函式same(i,j)表示如果s[i] == t[j]則為0,否則為1。

我們來表示一下遞推式:

f(i,j) = min(f(i – 1, j – 1) + same(i,j), f(i – 1,j ) + 1, f(i, j – 1) + 1)

初值是什麼?

f(0, j) = j

f(i, 0) = i

這時因為對於s的前0位,我們只能在之前加入「-」,或者說把t全部刪掉了。類似地,對於t地前0位,我們只能把s的字元都加進來,別無選擇。

注意上述兩個式子的重合點 f(0,0) = 0也符合我們的定義,並不矛盾。

時間複雜度? o(m * n),空間複雜度? o(m * n)。同樣我們發現到f(i,j)只與本行和上一行有關,可以省掉一維的空間複雜度,從而達到o(n)。

優化後的偽**:

1

2

3

4

5

6

7

8

9

10

11

12

13

forj=

0tondo

f[j]=j

endfor

fori=

1tomdo

last=f

[0]

f[0]=i

forj=1

tondo

temp=f

[i,j]

f[i, j]=

min(

last

+same(i,

j),  temp

+1, 

f[j – 

1]+1)

last

=temp

endfor

endfor

注意: 我們對於i實際上更新j的順序是由小到達的,所以我們需要儲存「舊的」f[i-1,j – 1]。

最後,我們來提供輸入輸出資料,由你來寫一段程式,實現這個演算法,只有寫出了正確的程式,才能繼續後面的課程。

輸入

第1行:字串a(a的長度 <= 1000)。

第2行:字串b(b的長度 <= 1000)。

輸出

輸出a和b的編輯距離
輸入示例

kitten

sitting

輸出示例

3

51Nod 1183 編輯距離(dp)

題意 編輯距離,又稱levenshtein距離 也叫做edit distance 是指兩個字串之間,由乙個轉成另乙個所需的最少編輯操作次數。許可的編輯操作包括將乙個字元替換成另乙個字元,插入乙個字元,刪除乙個字元。例如將kitten一字轉成sitting sitten k s sittin e i ...

51nod 1183 編輯距離 (dp)

編輯距離,又稱levenshtein距離 也叫做edit distance 是指兩個字串之間,由乙個轉成另乙個所需的最少編輯操作次數。許可的編輯操作包括將乙個字元替換成另乙個字元,插入乙個字元,刪除乙個字元。例如將kitten一字轉成sitting sitten k s sittin e i sit...

51Nod 1183 編輯距離(DP)

題目描述 思路 設 d p i j dp i j dp i j 表示把字串a的前i個字元變成字串b的前j個字元的編輯距離,有轉移方程 d p i 1 j 1 dp i j a i b j 0 1 dp i j 1 1 dp i 1 j 1 end dp i 1 j 1 dp i j a i b j ...