问题描述:
给定一些 DNA 序列 t 行 ,为了标记,往每一行的随机位置中添加一个特殊序列,每一行添加的都是一样的序列。
插入的序列可能会产生基因突变,部分碱基会发生改变。
现在,要已经知道 DNA 序列,插入序列的长度 l , 因为插入的序列不稳定,很可能会发生基因突变,要找出最可能的一致串 l 。
尝试长度为 l 的每一个序列,该序列上每一个位置都有四种可能 a c g t ,用该序列和DNA的每一行寻找长度也为 l 的,海明距离最短的串,所有行的海明距离之和最短的,acgt 序列就可能是最优解。
复杂度很高 O ( t * l * l * num ^ l )
只能处理一些简单的序列,只是实现了简单的想法,正确性不明。日后会学习更好的算法。
#include <bits/stdc++.h>
using namespace std ;
#define INF 0x3f3f3f3f
int t , l , num ; // DNA 序列 t 行, 插入的碱基长度 l, num 个碱基
char pattern[105] ; // 保存碱基
string DNA[1005] ; // 保存 DNA
string cur ;
int best_distance ; // 保存最优解
vector < string > best ;
inline Hai_Ming_distance ( const string &cur , const string &DNA_i ) {
int ans = 0 ;
for ( int t = 0 ; t < (int)cur.size () ; ++t ) // 求两个串的海明距离
if ( cur[t] != DNA_i[t] )
++ans ;
return ans ;
}
int Total_distance ( const string &cur ) {
int ans = 0 ;
int len = (int)cur.size () ;
for ( int i = 1 ; i <= t ; ++i ) { // 针对 DNA 序列的每一行
int cnt = INF ;
for ( int j = 0 ; j < (int)DNA[i].size () - l + 1 ; ++j ) {
int now = Hai_Ming_distance ( cur , DNA[i].substr ( j , len ) ) ; // 对该行所有长度为 len 的串和 cur 求海明距离
cnt = min ( cnt , now ) ; // 求该行和 cur 海明距离最短的(len)串
}
if ( cnt != INF )
ans += cnt ; // ans 累加每一行最佳串和 cur 的海明距离
}
return ans ;
}
void DFS ( string cur , int x ) {
int ans = Total_distance ( cur ) ;
if ( ans > best_distance ) // 如果都搜索到当前的海明距离之和已经 > 最优解
return ; // 剪枝, 不搜索它的子树, 因为子树产生的海明距离之和更大
if ( x == l ) {
if ( ans == best_distance ) // 又出现最优解
best.push_back ( cur ) ;
else if ( ans < best_distance ) { // 出现更优解
best.clear () ; // 之前的最优解清空
best.push_back ( cur ) ; // 从现在开始记录最优解
best_distance = ans ; // 更新最优解
}
return ;
}
for ( int i = 1 ; i <= num ; ++i ) // 对当前位置 x 尝试四种碱基
DFS ( cur + pattern[i] , x + 1 ) ; // 复杂度 num ^ l
}
void Init () {
cout << "碱基字符个数 : " ;
cin >> num ;
cout << endl << "碱基字符集 : " ;
for ( int i = 1 ; i <= num ; ++i )
cin >> pattern[i] ;
cout << endl << "DNA 序列的行数 : " ;
cin >> t ;
cout << endl << "插入的碱基序列长度 : " ;
cin >> l ;
cout << endl << "请输入 DNA 序列 : " << endl ;
for ( int i = 1 ; i <= t ; ++i )
cin >> DNA[i] ;
for ( int i = 1 ; i <= t ; ++i )
cout << DNA[i] << endl ;
cur = "" ;
best_distance = INF ;
}
void Make_Best () {
cout << endl << "最优海明距离 : " << best_distance << endl << endl ;
cout << "最优的插入串可能是 : " << endl << endl ;
for ( int i = 0 ; i < (int)best.size () ; ++i )
cout << best[i] << endl << endl ;
}
int main () {
Init () ; // 初始化
DFS ( cur , 0 ) ; // 开始深度优先搜索
Make_Best () ; // 列举最优解
return 0 ;
}
结果