1080 Human Gene Functions

1080 Human Gene Functions


2つの遺伝子がどれだけ似ているか(similarity)を計算する。
これまたPKUに興味を持つきっかけになった1159 Palindrome(halwhiteがLCSを教えてくれて解けた)に似ているなぁと思ってDPの練習としてやってみた。

dp[i][j]をseq1のi文字目、seq2のj文字目までのsimilarityの最大値とする。

  • dp[0][0]は0
  • dp[0][i2] (1≦i2≦len2)はseq2に全てワイルドカード'-'をぶつけた場合だから、徐々にsimilarityは下がっていく。
  • dp[i1][0] (1≦i1≦len1)はseq1に全てワイルドカード'-'をぶつけた場合だから、徐々にsimilarityは下がっていく。
  • dp[i1][i2] (1≦i1≦len1, 1≦i2≦len2)は場合分け。


seq1 ○○○☆
seq2 ××☆

dp[i1][i2] = dp[i1-1][i2-1] + calcScore(seq1[i1-1], seq2[i2-1]); // (=5)


seq1 ○○○□
seq2 ××△

dp[i1][i2] = max(dp[i1-1][i2-1] + calcScore(seq1[i1-1], seq2[i2-1]), // □と△を対応させた場合
                 dp[i1-1][i2] + calcScore('-', seq1[i1-1]), // □にワイルドカードを対応させた場合
                 dp[i1][i2-1] + calcScore('-', seq2[i2-1])) // △にワイルドカードを対応させた場合

LCSの応用形だった。

#include<cstdio>
#include<algorithm>

using namespace std;

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 calcScore(char c1, char c2) {
    int i1, i2;
    switch (c1) {
    case 'A':
	i1 = 0;
	break;
    case 'C':
	i1 = 1;
	break;
    case 'G':
	i1 = 2;
	break;
    case 'T':
	i1 = 3;
	break;
    case '-':
	i1 = 4;
	break;
    }
    switch (c2) {
    case 'A':
	i2 = 0;
	break;
    case 'C':
	i2 = 1;
	break;
    case 'G':
	i2 = 2;
	break;
    case 'T':
	i2 = 3;
	break;
    case '-':
	i2 = 4;
	break;
    }
    return score[i1][i2];
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
	int len1, len2;
	char seq1[101], seq2[101];
	scanf("%d %s %d %s", &len1, seq1, &len2, seq2);
	int dp[len1+1][len2+1];
	dp[0][0] = 0;
	for (int i2 = 1; i2 <= len2; ++i2) {
	    dp[0][i2] = dp[0][i2-1] + calcScore('-', seq2[i2-1]);
	}
	for (int i1 = 1; i1 <= len1; ++i1) {
	    dp[i1][0] = dp[i1-1][0] + calcScore('-', seq1[i1-1]);
	}

	for (int i1 = 1; i1 <= len1; ++i1) {
	    for (int i2 = 1; i2 <= len2; ++i2) {
		if (seq1[i1-1] == seq2[i2-1]) {
		    dp[i1][i2] = dp[i1-1][i2-1] + calcScore(seq1[i1-1], seq2[i2-1]);
		}
		else {
		    dp[i1][i2] = max(dp[i1-1][i2-1] + calcScore(seq1[i1-1], seq2[i2-1]),
				     max(dp[i1-1][i2] + calcScore('-', seq1[i1-1]),
					 dp[i1][i2-1] + calcScore('-', seq2[i2-1])));
					 
		}
	    }
	}
	printf("%d\n", dp[len1][len2]);
    }
}

calcScoreのところをうまく書けないかなぁ…
MAPとか?