原创:hxj7
关于全局联配的介绍可参见前文:
序列比对(一)全局比对Needleman-Wunsch算法
序列比对(二)Needleman-Wunsch算法之仿射罚分
所谓局部联配,就是两条序列的子序列的联配。局部联配算法就是找到联配得分最高的子序列。其中最常见的就是Smith-Waterman算法。
Smith-Waterman算法与Needleman-Wunsch算法类似,只是在计算得分矩阵分值的时候加了一个限制,即分值不能是负数。具体如下:
图片引自《生物序列分析》
算法的注意点是:
- 如果得分矩阵M(i, j)的分值被设置为0,其意义就是序列X(1,2,…i)与Y(1,2,…j)都不参与最终的联配。
- M(i,0)以及M(0, j)的分值需设置为0。
- 回溯的中止条件是遇到分值为0的得分单元。
全局联配和局部联配结果的区别:
(alignNW代表全局联配,alignSW代表局部联配)
C代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSEQ 1000
#define GAP_CHAR '-'
// 对空位的罚分是线性的
struct Unit {
int W1; // 是否往上回溯一格
int W2; // 是否往左上回溯一格
int W3; // 是否往左回溯一格
float M; // 得分矩阵第(i, j)这个单元的分值,即序列s(1,...,i)与序列r(1,...,j)比对的最高得分
};
typedef struct Unit *pUnit;
void strUpper(char *s);
float max4(float a, float b, float c, float d);
float getFScore(char a, char b);
void printAlign(pUnit** a, const int i, const int j, char* s, char* r, char* saln, char* raln, int n);
void align(char *s, char *r);
int main() {
char s[MAXSEQ];
char r[MAXSEQ];
printf("The 1st seq: ");
scanf("%s", s);
printf("The 2nd seq: ");
scanf("%s", r);
align(s, r);
return 0;
}
void strUpper(char *s) {
while (*s != '\0') {
if (*s >= 'a' && *s <= 'z') {
*s -= 32;
}
s++;
}
}
float max4(float a, float b, float c, float d) {
float f = a > b ? a : b;
float g = c > d ? c : d;
return f > g ? f : g;