//题意:给你一串碱基序列,将每队碱基配对都有得分,如图给的碱基表,当然可以其中有碱基对空,求最高分
//思路:通过状态转移,从头至尾扫描,变形的最长公共子序列,(相同碱基配对得分最高)那么此时要么碱基配碱基,要么碱基配空则见代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
char c1[200];
char c2[200];
int p[200][200];
int d[200][200];
int max_(int a, int b, int c) //三种状态选最优的
{
int d;
d = a > b ? a : b;
d = d > c ? d : c;
return d;
}
int main()
{
int t;
while(scanf("%d", &t) != EOF){
p['A']['A']=5;//表格的初始化一定要细心,不要因为表格输入错误而WA
p['C']['C']=5;
p['G']['G']=5;
p['T']['T']=5;
p['-']['-']=-1;
p['A']['C']=p['C']['A']=-1;
p['A']['G']=p['G']['A']=-2;
p['A']['T']=p['T']['A']=-1;
p['A']['-']=p['-']['A']=-3;
p['C']['G']=p['G']['C']=-3;
p['C']['T']=p['T']['C']=-2;
p['C']['-']=p['-']['C']=-4;
p['G']['T']=p['T']['G']=-2;
p['G']['-']=p['-']['G']=-2;
p['T']['-']=p['-']['T']=-1;
while(t--){
int len1, len2;
scanf("%d%s%d%s",&len1, c1, &len2, c2);
memset(d, 0, sizeof(d));
for(int i = 1; i <= len2; i++){
d[i][0] = d[i-1][0] + p[c2[i-1]]['-'];
}
for(int i = 1; i <= len1; i++){
d[0][i] = d[0][i-1] + p[c1[i-1]]['-'];
}
for(int i = 1; i <= len2; i++){
for(int j = 1; j <= len1; j++){
d[i][j] = max_( d[i-1][j-1] + p[c2[i-1]][c1[j-1]],//前一个状态的碱基配碱基得分 (d为某状态下的总得分,p为特定碱基的得分)
d[i-1][j] + p[c2[i-1]]['-'], //两条字符串中的一条碱基配空得分
d[i][j-1] + p[c1[j-1]]['-'] //两条字符串中的另一条碱基配空得分
);
}
}
cout << d[len2][len1] << endl;
}
}
return 0;
}