一、問題分析:
本題提出了一些關於將字串x[1..m]轉換成y[1..n]的操作。這些操作有複製、替代、刪除、插入、互換和終止。這些操作所需的開銷是不同的,但每個操作的開銷都可以看是乙個我們已經的常量,我們假設複製和替代這類操作的開銷要比插入和刪除這類操作的開銷少。我們用x[1..m]來儲存原字串,陣列下標用i表示,初始化為1;用y[1..n]來儲存轉換後的字串,陣列下標用j來表示,初始化為1;陣列z用來存放中間結果,下標用j來表示,初始化為0。
題目有兩個待解決的問題:第一,給定兩個序列x[1..m]和y[1..n]以及變換操作開銷的集合。從x到y的編輯距離指的就是將x轉換成y時的最小開銷的操作序列。用動態規劃的演算法找出從x到y的編輯距離並輸出最優操作序列。分析演算法的時空複雜度。第二, 解釋如何從給定的編輯操作集選擇乙個子集,從而把尋找總分最高的對齊結果的問題,轉化為求序列編輯距離的問題的乙個特例。
二、演算法分析:
問題a解答:
老師在上課的時候對這道題目進行過討論,它跟最長公共子串行的問題十分類似。因此,我仿照最長公共子串行問題的方法來求解這個問題。首先,定義了兩個序列xi=x[1,2,...,m]和yj=y[1,2,…,n],題目所求的就是將序列xi變為yj的編輯操作序列的最小開銷。
刻畫最優解的結構:對於序列xi(0≤i≤m)和序列yj(0≤j≤n)來說,定義c[i,j]為xi轉換成yj的操作序列的最小開銷。假定我們已經知道了最後一次執行的操作,此時分情況討論問題的最優解結構。
1.最後一次操作為copy。此時,根據題目的定義可知x[i]=y[j],我們待解決的問題就轉化成了求將xi-1轉換為yj-1的最小開銷。將xi-1轉換為yj-1的最優解一定包含在xi轉換為yj的最優解內。用反證法證明:若存在從xi-1到yj-1轉換的更小的開銷,那麼用這個更小的開銷來代替xi-1轉換為yj-1的最優解,這樣就會得到乙個更小的從xi轉換為yj的開銷,與已知的xi轉換為yj的最優解矛盾,所以假設不成立。因此,當最後一次操作為copy時,可以定義c[i,j]=c[i-1,j-1]+cost(copy)。
2.最後一次操作為replace。此時,根據題目的定義可知x[i]≠y[j]。仿照上述分析,可以得到相同的最優子結構。此時c[i,j]=c[i-1,j-1]+cost(replace)。
3.最後一次操作為delete。根據題意,這時只是將x[i]從序列xi中除去,對序列yj沒有任何影響,此時問題的最優子結構的形式為將xi-1轉換成yj,於是可以得到c[i,j]=c[i-1,j]+cost(delete)。
4.最後一次操作為insert。根據題意,在進行插入操作時,序列xi無任何變化,序列yj新增乙個字元,因此,這時候問題的最優子結構的形式為將xi轉換成為yj-1,此時c[i,j]=c[i,j-1]+cost(insert)。
5.最後一次操作為twiddle。根據題意,互換操作是針對兩個字元進行的,此時有y[j]=x[i-1]和y[j-1]=x[i]。在進行這個操作的時候,需要滿足的條件是i,j≥2。在這種情況下,問題的最優子結構的形式為xi-2轉換為yi-2,此時c[i,j]=c[i-2,j-2]+cost(twiddle)。
6.最後一次操作為kill。這種情況比較特殊,由於kill操作可以一次刪除乙個子串,對所有i=1..m-1, j=1..n,當x被檢查到xi,y被生成到yj的時候,用乙個kill操作可以刪除x中剩下的元素,用(n-i)個insert操作可以插入y中尚未出現的全部元素。這樣即可把x中的元素全部檢查到,並且生成完整的y。這種方式把x變成y的總開銷為c[i][j]+cost(kill)+(n-i) *cost(insert)。對所有c[i][j]求這個值,並且和上述忽略kill操作的前提下求出的編輯距離相比,取其中最小值,即求得編輯距離。
考慮一些特殊的情況,當x和y為空串時,c[0,0]=0。當xi為乙個非空序列yj為空序列時,可以很明顯的看出此時的操作全為delete,因此有c[i,0]=i*cost(delete)。當xi為乙個空序列yj為非空序列時,可以很明顯的看出此時的操作全為insert,因此有c[0,j]=j*cost(insert)
演算法的偽**如下所示:
edit-distance(x,y,m,n)
for i←0 to m
do c[i,0]=i*cost(delete)
op[i,0] ←delete
for j←0 to n
do c[0,j]=j*cost(insert)
op[j,0] ←insert
for i←1 to m
do for j←1 to n
do c[i,j] ←∞
if x[i]=y[j]
then c[i,j] ←c[i-1,j-1]+cost(copy)
op[i,j] ←copy
if x[i]≠y[j] and c[i-1,j-1]+cost(replace)then c[i,j]= c[i-1,j-1]+cost(replace)
op[i,j] ← replace
if c[i-1,j]+cost(delete)then c[i,j] ←c[i-1,j]+cost(delete)
op ←delete
if c[i,j-1]+cost(insert)then c[i,j]←c[i,j-1]+cost(insert)
op ← insert
if i≥2 and j≥2 and x[i-1]=y[j] and x[i]=y[j-1] and c[i-2,j-2]+cost(twiddle)then c[i,j]= c[i-2,j-2]+cost(twiddle)
op ← twiddle
for i ←0 to m-1
do if c[i,n]+cost(kill)then c[m,n]←c[i,n]+cost(kill)
op[m,n]←killi
return c and op
演算法的時間複雜度分析:該演算法是對乙個(m+1)(n+1)的**進行填寫的過程,填寫每乙個格c[i][j]花費的開銷,只是根據 c[i-1][j], c[i][j-1], c[i-1][j-1], c[i-2][j-1]進行簡單的加減運算,得到五個數字,選擇其中最小的乙個。所以該演算法的時間複雜度為o(mn)。
最後構造問題的最優解,編輯序列輸出的演算法偽**如下所示:
out-operation(op,i,j)
if i=0 and j=0
then return
if op[i,j] = copy or op[i,j] = replace
then i』←i-1
j』←j-1
else if op[i,j]=delete
then i』=i-1
j』=j
else if op[i,j] = insert
then i』=i
j』=j-1
else if op[i,j]=twiddle
then i』=i-2
j』=j-2
else
let op[i,j]=killk
i』=k
j』=j
out-operation(op,i』,j』)
print op[i,j]
問題b解答:
在dna對齊問題中,最高得分的對齊方法可以通過選擇下面四個操作並相應賦給開銷,來轉換成乙個編輯距離問題:
insert, -2
delete, -2
copy, +1
replace, -1
(1)如果x1[j]==y1[j],1分;對應的是copy操作;
(2)如果x1[i]!=y1[j]並且兩者都不是空格,-1分;對應的是replace操作;
(3)如果x1[j]或者y1[j]是空格,-2分,對應的是insert和delete操作。
編輯距離及編輯距離演算法
編輯距離概念描述 編輯距離,又稱levenshtein距離,是指兩個字串之間,由乙個轉成另乙個所需的最少編輯操作次數。許可的編輯操作包括將乙個字元替換成另乙個字元,插入乙個字元,刪除乙個字元。例如將kitten一字轉成sitting sitten k s sittin e i sitting g 俄...
編輯距離及編輯距離演算法
include include include using namespace std const int max 1001 int maxlen max max int maxlen string str1,string str2 return maxlen len1 len2 int main ...
編輯距離及編輯距離演算法
include include include using namespace std const int max 1001 int maxlen max max int maxlen string str1,string str2 return maxlen len1 len2 int main ...