POJ 1080 Human Gene Functions (类似LCS)

本文介绍了一种使用动态规划算法解决两个由ACGT组成的字符串之间的最大相似值匹配问题的方法。通过构建一个5*5的映射表来表示字符间的相似度,并采用类似于最长公共子序列的思路,定义了状态转移方程,最终实现高效求解。

题目大意

  • 题目给出一张5*5的映射表,分别是ACGT-,每对字符都有一个相似值。
  • 给出两个字符串,由ACGT组成,求两个字符串匹配的最大相似值和,可以用-代替字符匹配。

分析

  • 类似求最长公共子序列
  • dp[i][j]表示s1中1….i和s2中的1….j匹配的最大相似值
  • 状态转移方程

    dp[i][j] = max{dp[i-1][j-1]+mp[a][b] , dp[i-1][j]+mp[a][4] , dp[i][j-1] + mp[4][b]}
    
  • 记得初始化 dp[0][i] 和dp[i][0]

代码

#include <iostream>
#include <cstring>

using namespace std;
int mp[5][5] = {
    {5 , -1 , -2 , -1 , -3} ,
    {-1 , 5 , -3 , -2 , -4} ,
    {-2 , -3 , 5 , -2 , -2} ,
    {-1 , -2 , -2 , 5 , -1} ,
    {-3 , -4 , -2 , -1 , 0}
};
const int maxn = 110;
int dp[maxn][maxn] = {{0} , {0}}; //dp[i][j]表示1..i匹配1..j时的最大相似值

int idx(char c)
{
    switch(c) {
        case 'A': return 0;
        case 'C': return 1;
        case 'G': return 2;
        case 'T': return 3;
    }
    return 4;
}
//dp[i][j] = max{dp[i-1][j-1]+mp[a][b] , dp[i-1][j]+mp[a][4] , dp[i][j-1] + mp[4][b]}
int main()
{
    int t; cin >> t;
    while(t--)
    {
        int len1 , len2;
        char s1[maxn] , s2[maxn];
        cin >> len1;
        for(int i = 1; i <= len1; i++) cin >> s1[i];
        cin >> len2;
        for(int i = 1; i <= len2; i++) cin >> s2[i];

        for(int i = 1; i <= len2; i++) {
            int k = idx(s2[i]);
            dp[0][i] = dp[0][i-1] + mp[4][k];
        }
        for(int i = 1; i <= len1; i++) {
            int k = idx(s1[i]);
            dp[i][0] = dp[i-1][0] + mp[k][4];
        }
        for(int i = 1; i <= len1; i++) for(int j = 1; j <= len2; j++) {
            int a = idx(s1[i]) , b = idx(s2[j]);
            dp[i][j] = dp[i-1][j-1] + mp[a][b];
            dp[i][j] = max(dp[i][j] , dp[i-1][j] + mp[a][4]);
            dp[i][j] = max(dp[i][j] , dp[i][j-1] + mp[4][b]);
        }
        cout << dp[len1][len2] << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值