Needleman-Wunsch 算法(C++实现)

本文实现Needleman-Wunsch 算法案例,用于全局序列比对。该算法是生物信息学中用于比较两个 DNA、RNA 或蛋白质序列的经典算法,通过动态规划找到最优的全局比对。


问题描述

给定两个生物序列 seq1seq2,如何找到它们的最优全局比对,使得比对得分最大化?


算法思想

Needleman-Wunsch 算法的核心思想是动态规划。通过构建一个得分矩阵,逐步计算两个序列的比对得分,并回溯找到最优比对路径。具体步骤如下:

  1. 初始化得分矩阵,其中 dp[i][j] 表示 seq1 的前 i 个字符与 seq2 的前 j 个字符的比对得分。
  2. 填充得分矩阵,考虑三种可能的比对操作:
    • 匹配或错配:dp[i-1][j-1] + score(seq1[i], seq2[j])
    • 插入空格:dp[i][j-1] + gap_penalty
    • 删除空格:dp[i-1][j] + gap_penalty
  3. 回溯得分矩阵,找到最优比对路径。

C++代码实现

#include 
#include 
#include 

using namespace std;

// 定义得分函数
int match_score(char a, char b) {
    return (a == b) ? 1 : -1;
}

// Needleman-Wunsch 算法
pair<int, string> needlemanWunsch(const string& seq1, const string& seq2, int gap_penalty = -1) {
    int m = seq1.size();
    int n = seq2.size();

    // 初始化得分矩阵
    vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0));
    for (int i = 1; i <= m; i++) {
        dp[i][0] = i * gap_penalty;
    }
    for (int j = 1; j <= n; j++) {
        dp[0][j] = j * gap_penalty;
    }

    // 填充得分矩阵
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            int match = dp[i - 1][j - 1] + match_score(seq1[i - 1], seq2[j - 1]);
            int insert = dp[i][j - 1] + gap_penalty;
            int del = dp[i - 1][j] + gap_penalty;
            dp[i][j] = max({match, insert, del});
        }
    }

    // 回溯找到最优比对
    string align1, align2;
    int i = m, j = n;
    while (i > 0 || j > 0) {
        if (i > 0 && j > 0 && dp[i][j] == dp[i - 1][j - 1] + match_score(seq1[i - 1], seq2[j - 1])) {
            align1 = seq1[i - 1] + align1;
            align2 = seq2[j - 1] + align2;
            i--;
            j--;
        } else if (i > 0 && dp[i][j] == dp[i - 1][j] + gap_penalty) {
            align1 = seq1[i - 1] + align1;
            align2 = '-' + align2;
            i--;
        } else {
            align1 = '-' + align1;
            align2 = seq2[j - 1] + align2;
            j--;
        }
    }

    return {dp[m][n], align1 + "\n" + align2};
}

int main() {
    string seq1 = "GATTACA";
    string seq2 = "GCATGCU";

    auto result = needlemanWunsch(seq1, seq2);
    cout << "最优比对得分: " << result.first << endl;
    cout << "最优比对结果: " << endl << result.second << endl;

    return 0;
}

关键解析

  1. 时间复杂度O(m * n),其中 mn 分别是两个序列的长度。
  2. 空间复杂度O(m * n),用于存储得分矩阵。
  3. 适用场景
    • 全局序列比对。
    • 比较 DNA、RNA 或蛋白质序列。

输出示例

最优比对得分: 0
最优比对结果:  
G-ATTACA
GCA-TGCU

总结

Needleman-Wunsch 算法是生物信息学中用于全局序列比对的经典算法,通过动态规划和回溯找到最优比对。

你可能感兴趣的:(C++算法设计与实现,算法,c++,开发语言)