1. 问题背景与理解
这道题目来自ICPC 2001年大田区域赛,要求我们计算两个基因序列的相似度。基因序列由A、C、G、T四种碱基组成,我们可以通过在序列中插入"-"(空位)来对齐两个序列,使得它们的相似度最大化。
在实际生物信息学中,这种序列比对是基础操作。比如在比较不同物种的DNA序列时,我们需要找到最优的比对方式,这直接关系到进化树构建、基因功能预测等重要研究。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 动态规划思路解析
2.1 状态定义
我们定义dp[i][j]表示:
- 第一个基因序列的前i个字符
- 第二个基因序列的前j个字符
- 通过最优比对后能获得的最大相似度得分
这个状态定义抓住了问题的核心——我们需要考虑两个序列所有可能的对齐方式,并找到得分最高的那种。
2.2 状态转移分析
状态转移考虑三种情况:
-
直接匹配:第一个序列的第i个字符与第二个序列的第j个字符匹配
- dp[i][j] = dp[i-1][j-1] + score(a[i], b[j])
-
第一个序列插入空位:第二个序列的第j个字符与空位匹配
- dp[i][j] = dp[i][j-1] + score('-', b[j])
-
第二个序列插入空位:第一个序列的第i个字符与空位匹配
- dp[i][j] = dp[i-1][j] + score(a[i], '-')
最终取这三种情况的最大值作为dp[i][j]的值。
2.3 初始化处理
边界条件需要特别注意:
- dp[0][0] = 0 (两个空序列相似度为0)
- dp[i][0] = dp[i-1][0] + score(a[i], '-') (第一个序列前i个字符全部与空位匹配)
- dp[0][j] = dp[0][j-1] + score('-', b[j]) (第二个序列前j个字符全部与空位匹配)
3. 代码实现详解
3.1 相似度得分矩阵
cpp复制int Money[5][5] = {
{5, -1, -2, -1, -3},
{-1, 5, -3, -2, -4},
{-2, -3, 5, -2, -2},
{-1, -2, -2, 5, -1},
{-
