A classic 2D DP problem. A disguise of LCS - actually not very hard to decode: it is about 2 sequences' matching, though with a weight value of each match.
The point of this problem: how to decode problem statement and how to distill the actuall model behind. Coding is not very hard, but my 80% debug time is spent on a stupid detail: in the 2 level for loop, indices start from 1, but char index of each string should be i - 1, j - 1.
Main reference: http://blog.csdn.net/xiaoxiaoluo/article/details/7366537
The AC code:
// 1080 // http://blog.csdn.net/xiaoxiaoluo/article/details/7366537 /* * Q1: What is the target value? Similarity Val * Q2: What are the Variables? indices of two strings * So, dp[i][j] = val * in which i is the index of 1st string, j is of the 2nd, and value is similarity * * The key is recurrence relations: * Eq1: s0[i] isChar, s1[j] isChar dp[i][j] = dp[i-1][j-1] + score[s0[i]][s1[j]] Eq2: s0[i] isChar, s1[j] is '-' dp[i][j] = dp[i][j-1] + score['-'][s1[j]] Eq3: s0[i] is '-', s1[j] isChar dp[i][j] = dp[i-1][j] + score[s0[i]]['-'] The above eqs are to simulate LCS eqs. '-' is artificially put to match strings */ #include <stdio.h> #define MAX_LEN 100 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 Inx(char c) { switch (c) { case 'A': return 0; case 'C': return 1; case 'G': return 2; case 'T': return 3; case '-': return 4; } } int max2(int a, int b) { return (a > b) ? (a) : (b); } int calc(int len0, char in0[MAX_LEN], int len1, char in1[MAX_LEN]) { int dp[MAX_LEN + 1][MAX_LEN + 1]; // Init dp[0][0] = 0; for (int i = 1; i <= len0; i ++) { dp[i][0] = dp[i - 1][0] + score[Inx(in0[i-1])][Inx('-')]; // eq2 } for (int j = 1; j <= len1; j++) { dp[0][j] = dp[0][j - 1] + score[Inx('-')][Inx(in1[j-1])]; // eq1 } // Go for (int i = 1; i <= len0; i ++) for (int j = 1; j <= len1; j ++) { int val0 = dp[i - 1][j - 1] + score[Inx(in0[i-1])][Inx(in1[j-1])]; int val1 = dp[i][j - 1] + score[Inx('-')][Inx(in1[j-1])]; int val2 = dp[i - 1][j] + score[Inx(in0[i-1])][Inx('-')]; dp[i][j] = max2(val0, max2(val1, val2)); } return dp[len0][len1]; } int main() { int n; scanf("%d", &n); while (n--) { int len[2] = { 0 }; char in0[MAX_LEN] = { 0 }; char in1[MAX_LEN] = { 0 }; scanf("%d", len); scanf("%s", in0); scanf("%d", len + 1); scanf("%s", in1); int ret = calc(len[0], in0, len[1], in1); printf("%d ", ret); } return 0; }