本文介紹如何求解兩個字串的最長公共子串行。前文《序列比對(23)最長公共子字串》介紹了如何求解兩個字串的最長公共子字串,本文將介紹如何求解兩個字串的最長公共子串行。二者聽起來很像,所以我們首先得說明一下
子字串
和子串行
的區別。
在本文語境中,子字串是由原字串中的連續字元組成;而子串行是從原字串中選擇字元,只需要保持其次序不變(可以說,子字串都是子串行,但子串行不一定是子字串)。比如:對於v=a
gc
t\bm=agct
v=agct
這個字串,agag
ag既是其子字串也是子串行;acac
ac是子串行而非子字串;caca
ca既非子字串也非子串行。
給定兩個字串v
\bmv和w
\bmw,長度分別為m
mm和n
nn,如何找到這兩個字串的最長公共子串行呢?舉例來說:如果v=a
gc
t\bm=agct
v=agct
,而w =t
ac
\bm=tac
w=ta
c,那麼二者的最長公共子串行就是acac
ac。與最長公共子字串問題類似,最長公共子串行問題也是一種序列比對問題,可以用動態規劃解決,只是在迭代時允許插入和缺失,而不允許錯配而已。如果是匹配,得分為1,否則得分為0。其迭代公式如下:
f (i
,j
)is the maximum score of alignments between x1
…i
and y1
…j.f
(i,0
)=
0for i=
0…m.
f(0,
j)=0
for j=
1…n.
f(i,
j)
=max
& \text$ and $y_$.} \\ & f(i, 0) = 0 \quad \text \\ & f(0, j) = 0 \quad \text \\ & f(i, j) = \max \begin f(i - 1, j), \\ f(i, j - 1), \\ f(i - 1, j - 1) + 1 \quad \text \end \end
f(i,j
)is the maximum score of alignments between x1
…iand y1
…j.
f(i,
0)=0
for i=
0…m.
f(0,
j)=0
for j=
1…n.
f(i,
j)=max⎩⎪
⎨⎪⎧
f(i−
1,j)
,f(i
,j−1
),f(
i−1,
j−1)
+1if xi
=yj
.回溯的時候從得分矩陣的右下角開始,一直到值為0的單元。回溯過程中只記錄xi=
yj
x_i = y_j
xi=yj
的單元對應的字元。
具體**如下:
#include
#include
#include
#define maxseq 1000
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
struct unit
;typedef
struct unit *punit;
void
strupper
(char
*s);
void
printalign
(punit*
* a,
const
int i,
const
int j,
char
* s,
char
* r,
int* is,
int* ir,
int n)
;void
align
(char
*s,char
*r);
intmain()
void
strupper
(char
*s) s++;}
}void
printalign
(punit*
* a,
const
int i,
const
int j,
char
* s,
char
* r,
int* is,
int* ir,
int n)
if(p->w1)
// 向上回溯一格
printalign
(a, i -
1, j, s, r, is, ir, n);if
(p->w2)
if(p->w3)
// 向左回溯一格
printalign
(a, i, j -
1, s, r, is, ir, n);}
void
align
(char
*s,char
*r)for
(i =
0; i <= m; i++
)for
(j =
0; j <= n; j++
) aunit[i]
[j]->w1 =0;
aunit[i]
[j]->w2 =0;
aunit[i]
[j]->w3 =0;
}}for(i =
0; i <= m; i++
) aunit[i][0
]->m =0;
for(j =
1; j <= n; j++
) aunit[0]
[j]->m =0;
// 將字串都變成大寫
strupper
(s);
strupper
(r);
// 動態規劃演算法計算得分矩陣每個單元的分值
for(i =
1; i <= m; i++)}
/* // 列印得分矩陣
for (i = 0; i <= m; i++)
*/printf
("max score: %d\n"
, aunit[m]
[n]->m)
;// 列印最優比對結果,如果有多個,全部列印
// 遞迴法
if(aunit[m]
[n]->m ==0)
else
printalign
(aunit, m, n, s, r, sidx, ridx,0)
;// 釋放記憶體
free
(sidx)
;free
(ridx);}
for(i =
0; i <= m; i++
)free
(aunit)
;}
最長公共子串行
最長公共子串行也稱作最長公共子串 不要求連續 英文縮寫為lcs longest common substring 其定義是,乙個數列 s 如果分別是兩個或多個已知數列的子串行,且是所有符合此條件序列中最長的,則 s 稱為已知序列的最長公共子串行。動態規劃的乙個計算最長公共子串行的方法如下 以兩個序列...
最長公共子串行
最長公共子串行與最長公共子串的區別在於最長公共子串行不要求在原字串中是連續的,比如ade和abcde的最長公共子串行是ade。我們用動態規劃的方法來思考這個問題如是求解。首先要找到狀態轉移方程 等號約定,c1是s1的最右側字元,c2是s2的最右側字元,s1 是從s1中去除c1的部分,s2 是從s2中...
最長公共子串行
求x y 的最長公共子串行.蠻幹法 找出x的所有子串行,共2 m個 m是x的元素個數 對每乙個自序列檢視是否在y中,需要n次 n是y的元素個數 總的時間複雜度 o n 2 m 動態規劃演算法 xi yj 設 zk 是xi和yi的最長公共子串行.則 1 當xi yj時,則zk xi yj,且zk 1是...