首页 > 代码库 > POJ 1080 Human Gene Functions(求两字符串相似度:LCS变形)

POJ 1080 Human Gene Functions(求两字符串相似度:LCS变形)

POJ 1080 Human Gene Functions(求两字符串相似度:LCS变形)

http://poj.org/problem?id=1080

题意: HDU1080

       给你两个由字符A,C,G,T构造的字符串s1和s2, 现在你可以在这两个字符串中插入空格, 使得两串长相等(但是不能使得s1的空格对应s2的空格位置). 然后给你s1的特定字符对应s2中特定字符所能获得的分数矩阵:

       问你最后两个字符串所能获得的最大分数是多少?

分析:

       本题很类似于求字符串最短编辑距离或者求字符串LCS的问题, 都是从两个字符串的最后一个字符入手.

       令dp[i][j]==x表示原始串s1的前i个字符和s2的前j个字符通过插入空格能获得的最大分数为x.

       初始化:dp[0][0]=0, dp[i][0]和dp[0][i]为s1和s2前i个字符对应空格的分数.

       状态转移:

       dp[i][j] = max( dp[i-1][j-1]+[s1[i]和s2[j]对应的分数] , dp[i-1][j]+[s1[i]和空格对应的分数] , dp[i][j-1]+[空格和s2[j]对应的分数] )

       上述第一个表示s1和s2最后一个位置都加空格, 所以是原本的字符对比获取分数.

       第2个表示s1的最后一个字符和s2的末尾添加空格比较获取分数.

       第3个表示s1的末尾添加空格来和s2对比.

       最终所求:dp[len(s1)][len(s2)].

AC代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100+5;

int n,m;
int dp[maxn][maxn];
char s1[maxn],s2[maxn];
int score[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},
};
int id[500];

int main()
{
    id['A']=0;//A字符对应0编号
    id['C']=1;
    id['G']=2;
    id['T']=3;
    id[' ']=4;
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%s",&n,s1);
        scanf("%d%s",&m,s2);

        //初始化
        dp[0][0]=0;
        for(int i=1;i<=m;i++)
            dp[0][i]=dp[0][i-1]+score[id[' ']][id[s2[i-1]]];
        for(int i=1;i<=n;i++)
            dp[i][0]=dp[i-1][0]+score[id[' ']][id[s1[i-1]]];

        //递推过程
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            int id1=id[s1[i-1]], id2=id[s2[j-1]];
            dp[i][j]=dp[i-1][j-1]+score[id1][id2];
            int tmp=max( dp[i-1][j]+score[id1][4] , dp[i][j-1]+score[4][id2] );
            dp[i][j]=max(dp[i][j], tmp );
        }
        printf("%d\n",dp[n][m]);
    }
    return 0;
}

POJ 1080 Human Gene Functions(求两字符串相似度:LCS变形)