1. 程式人生 > >DNA基因鑑定----編輯距離DP

DNA基因鑑定----編輯距離DP

我們經常會聽說 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;
}