典型的DP,跟《算法导论》的最长公共子串很像。第一次有点粗心,两次次提交后AC。
#include <stdio.h>
#define SPACE '-'
int GetTableIndex(char c)
{
switch(c)
{
case 'A':
return 0;
case 'C':
return 1;
case 'G':
return 2;
case 'T':
return 3;
case SPACE:
return 4;
default:
return -1;
}
return -1;
}
int similarityTable[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 GetSimilarity(char c1, char c2)
{
int index1 = GetTableIndex(c1);
int index2 = GetTableIndex(c2);
return similarityTable[index1][index2];
}
int dp[101][101];
int CalcMaxSimilarity(char *strA, char *strB, int nLenA, int nLenB)
{
dp[0][0] = 0;
for (int i = 0; i < nLenA; i++)
{
dp[i + 1][0] = GetSimilarity(strA[i], SPACE) + dp[i][0];
}
for (int j = 0; j < nLenB; j++)
{
dp[0][j + 1] = GetSimilarity(strB[j], SPACE) + dp[0][j];
}
for (int i = 0; i < nLenA; i++)
{
for (int j = 0; j < nLenB; j++)
{
int s1 = dp[i][j + 1] + GetSimilarity(strA[i], SPACE);
int s2 = dp[i + 1][j] + GetSimilarity(strB[j], SPACE);
int s3 = GetSimilarity(strA[i], strB[j]);
if (i != 0 || j != 0)
{
s3 += dp[i][j];
}
int max = (s1 > s2) ? s1 : s2;
max = (max > s3) ? max : s3;
dp[i + 1][j + 1] = max;
}
}
return dp[nLenA][nLenB];
}
int main()
{
int nCase;
scanf("%d", &nCase);
while (nCase --)
{
char strA[101] = "";
char strB[101] = "";
int nLenA = 0;
int nLenB = 0;
scanf("%d %s", &nLenA, strA);
scanf("%d %s", &nLenB, strB);
int ret = CalcMaxSimilarity(strA, strB, nLenA, nLenB);
printf("%d\n", ret);
}
return 0;
}