生物信息基础 学习笔记 (2)

问题描述:

给定一些 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 ;
}

结果

 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值