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)。output第2行:字串b(b的長度 <= 1000)。
輸出a和b的編輯距離input示例
kittenoutput示例 3sitting
//遞推公式賊幾把難想啊
#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 ...