给定一个串,两个串有A,T,G,C组成,求其两两配对,可以各自插入如干个空格,求最后的和值得最大值。
可以定义如下状态,f[i][j]表示1串到第i位,2串到达第j位通过各自补充空格达到一一配对的最终最大值,这就意味着f[3][0]也是有意义的,表示1串的前三个与三个空格的最终结果。刚开始做的时候就是认为长的一个串一定不要添加空格导致后面否定了一些状态。
那么有状态转移方程f[i][j] = max{ f[i-1][j]+val[s1[i]]['-'], f[i][j-1]+val['-'][s2[j]], f[i-1][j-1]+val[s1[i]][s2[j]] }怎么样,与LCS很像吧,其实也就是对匹配进行了抽象。
代码如下:
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <queue> #include <vector> #include <stack> #include <list> #include <set> #define INF 0x7fffffff using namespace std; int mp[256], len1, len2, f[105][105]; char s1[105], s2[105]; int val[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}, }; void pre() { mp['A'] = 0, mp['C'] = 1, mp['G'] = 2; mp['T'] = 3, mp['-'] = 4; } int dfs(int x, int y) { // x, y是上下链的坐标 int Max = -INF; if (f[x][y] != -1) return f[x][y]; if (x) Max = max(Max, dfs(x-1, y)+val[mp[s1[x]]][4]); // 第一个序列的x元素对应空格 if (y) Max = max(Max, dfs(x, y-1)+val[4][mp[s2[y]]]); if (x && y) Max = max(Max, dfs(x-1, y-1)+val[mp[s1[x]]][mp[s2[y]]]); return f[x][y] = Max; } int main() { int T; pre(); scanf("%d", &T); while (T--) { memset(f, 0xff, sizeof (f)); f[0][0] = 0; scanf("%d", &len1); if (len1) scanf("%s", s1+1); scanf("%d", &len2); if (len2) scanf("%s", s2+1); printf("%d\n", dfs(len1, len2)); } return 0; }