DNA基因鑑定----編輯距離DP
阿新 • • 發佈:2019-02-04
我們經常會聽說 DNA 親子鑑定是怎麼回事呢?人類的 DNA 由 4 個基本字母{A,C,G,T}構成,包含了成千上億個字元。如果兩個人的 DNA序列相差 0.1%,仍然意味著有 300 萬個位置不同,所以我們通常看到的 DNA 親子鑑定報告上結論有:相似度 99.99%,不排除親子關係。
怎麼判斷兩個基因的相似度呢?生物學上給出了一種編輯距離的概念。
例如兩個字串 FAMILY 和 FRAME,有兩種
對齊方式:
F - A M I L Y - F A M I L Y
F R A M E F R A M E
第 1 種對齊需要付出的代價:4,插入 R,將 I 替換為 E,刪除 L、Y。
第 2 種對齊需要付出的代價:5,插入 F,將 F 替換為 R,將 I 替換為 E,刪除 L、Y。
編輯距離是指將一個字串變換為另一個字串所需要的最小編輯操作。
怎麼找到兩個字串 x[1,…,m]和 y[1,…,n]的編輯距離呢?
分析問題:
如果直接暴力列舉,可想而知需要運算的次數會隨著字串的增長而暴增,我們可以通過分析它是否具有最優子結構來決定能不能用動態規劃。
假設的d[i][j]是X和Y的編輯距離最優解。那麼不管兩序列怎麼對齊,都只可能有以下三種:
①:需要刪除xi,付出代價+1,即d[i][j]=d[i-1][j]+1;
②:需要刪除yj,付出代價+1,即d[i][j]=d[i][j-1]+1;
③:如果xi≠yj,則需要替換,付出代價+1,即d[i][j]=d[i-1][j-1]+1;若xi=yj,則付出代價為0;
我們可以由上推出最優值遞迴式:d[i][j]=min{d[i-1][j]+1,d[i][j-1]+1,d[i-1][j-1]+flag}//flag用xi是否等於yj來賦值。
程式碼詳解:
#include<iostream> #include<string.h> using namespace std; const int N = 1000; char s1[N], s2[N]; int d[N][N]; int min(int a,int b) { return a < b ? a : b; } int judge(char *s1, char *s2) { int len1 = strlen(s1); int len2 = strlen(s2); for (int i = 0; i <= len1; i++) d[i][0] = i; for (int i = 0; i <= len2; i++) d[0][i] = i; for (int i = 1; i <= len1; i++) { for (int j = 1; j <= len2; j++) { int flag;//用來標誌xi和yj是否相等 if (s1[i] == s2[j]) flag = 0; else flag = 1; int temp = min(d[i - 1][j] + 1, d[i][j - 1] + 1);//先比較前兩個的值 d[i][j] = min(temp, d[i - 1][j - 1] + flag); } } return d[len1][len2]; } int main() { cin >> s1; cin >> s2; cout << judge(s1, s2) << endl; return 0; }