题目链接:
https://cn.vjudge.net/problem/POJ-1080
题目大意:
给定两组序列,要你求出它们的最大相似度,每个字母与其他字母或自身和空格对应都有一个打分,求在这两个字符串中插入空格,让这两个字符串的匹配分数最大
解题思路:
类似LCS,以dp[i][j]表示s1前i位和s2前j位的最优解。
递推式为:
先不考虑括号
dp[i][j]只由dp[i-1][j-1]递推而来
if(s1[i] == s2[j])dp[i][j] = dp[i - 1][j - 1] + 5
else dp[i][j] = dp[i - 1][j - 1] + Map[id1][id2]此处Map[id1][id2]为s1[i]和s2[j]匹配的分数
考虑括号
dp[i][j]在原来基础上可以由dp[i-1][j]和dp[i][j-1]递推而来
由dp[i-1][j]递推而来的时候是s1[i]和空格匹配
由dp[i][j-1]递推而来的时候是空格和s2[j]匹配
dp[i][j] = max(dp[i][j],dp[i-1][j] + Map[id1][空格], dp[i][j - 1] + Map[空格][id2])
注意:
要初始化dp[0][i]和dp[j][0]的值(不能单纯的置为0,置为0是错误的),dp[0][0]=0
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<sstream> 10 #define Mem(a, b) memset(a, b, sizeof(a)) 11 using namespace std; 12 typedef long long ll; 13 const int INF = 1e9+7; 14 int dp[105][105]; 15 int Map[5][5] = 16 { 17 5,-1,-2,-1,-3, 18 -1,5,-3,-2,-4, 19 -2,-3,5,-2,-2, 20 -1,-2,-2,5,-1, 21 -3,-4,-2,-1,0, 22 }; 23 char s1[105], s2[105]; 24 int main() 25 { 26 map<char, int>id; 27 id['A'] = 0; 28 id['C'] = 1; 29 id['G'] = 2; 30 id['T'] = 3; 31 id[' '] = 4; 32 int T, n, m; 33 cin >> T; 34 while(T--) 35 { 36 cin >> n >> (s1 + 1); 37 cin >> m >> (s2 + 1); 38 Mem(dp, 0); 39 for(int i = 1; i <= n; i++) 40 { 41 dp[i][0] = dp[i - 1][0] + Map[id[s1[i]]][id[' ']]; 42 } 43 for(int i = 1; i <= m; i++) 44 { 45 dp[0][i] = dp[0][i - 1] + Map[id[' ']][id[s2[i]]]; 46 } 47 for(int i = 1; i <= n; i++) 48 { 49 for(int j = 1; j <= m; j++) 50 { 51 if(s1[i] == s2[j]) 52 dp[i][j] = dp[i - 1][j - 1] + 5; 53 else 54 dp[i][j] = dp[i - 1][j - 1] + Map[id[s1[i]]][id[s2[j]]]; 55 //cout<<i<<" "<<j<<" "<<dp[i][j]<<endl; 56 dp[i][j] = max(dp[i][j], dp[i - 1][j] + Map[id[s1[i]]][id[' ']]); 57 dp[i][j] = max(dp[i][j], dp[i][j - 1] + Map[id[' ']][id[s2[j]]]); 58 //cout<<i<<" "<<j<<" "<<dp[i][j]<<endl; 59 } 60 // 61 } 62 cout<<dp[n][m]<<endl; 63 } 64 return 0; 65 }