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;
}