高级数据结构与算法(一):Smith-Waterman算法及matlab实现

1.概念

史密斯-沃特曼算法(Smith-Waterman algorithm)是一种进行局部序列比对(相对于全局比对)的算法,该算法的目的不是进行全序列的比对,而是找出两个序列中具有高相似度的片段。可简称为SW算法。

2.过程

2.1算法目的

寻找具有最高相似性的局部序列,进行局部序列匹配。

2.2基本假设

比对的两序列为:
在这里插入图片描述
则两序列的长度分别为len(A) = n,Len(B)=m;
s(a,b):字符a和字符b的相似分数;
H:匹配分数矩阵
W_{1} = 2 :一个空位罚分,这里设置为2(可根据需要设置)

2.3算法步骤

1.初始化算法分数矩阵H,使行i表示字符a_{i},列j表示字符b_{j}

2.计算矩阵中每一项的H_{ij}

\left.H_{ij}=\max\left\{\begin{matrix}H_{i-1,j-1}+s(a_i,b_j),\\H_{i-1,j}-W_1,\\H_{i,j-1}-W_1,\\0\end{matrix}\right.\right.S\left(a_i,b_j\right)=\begin{cases}+3,\quad&a_i=b_j\\-3,\quad&a_i\neq b_j\\\end{cases}


3.回溯,从矩阵H中分数最大的一项开始:
a_{i}=b_{j},则回溯到左上角单元格
a_{i}\neq b_{j},回溯到左上角、上边、左边中值最大的单元格,若有相同最大值的单元格,优先级按照左上角、上边、左边的顺序

4.根据回溯路径,写出匹配字符串:
若回溯到左上角单元格,将a_{i}添加到匹配字串A‘,将b_{j}添加到匹配字串B’;
若回溯到上边单元格,将a_{i}添加到匹配字串A’,将_添加到匹配字串B’;
若回溯到左边单元格,将_添加到匹配字串A’,将b_{j}添加到匹配字串B’。

5.得到局部最优匹配序列,结束

3.代码实现

clc;clear;
x1=input("请输入序列一:",'s');
x2=input("请输入序列二:",'s');
W1=2;
H=zeros(length(x2)+1,length(x1)+1);
for i=2:length(x2)+1
    for j=2:length(x1)+1
        if(x1(j-1)==x2(i-1))
            s=3;
        else
            s=-3;
        end
        a=H(i-1,j-1)+s;
        H(i,j)=max([a,H(i-1,j)-W1,H(i,j-1)-W1,0]);
    end
end
[n1,m1]=find(H==max(max(H)'));
n(1)=n1;
m(1)=m1;
i=1;
while(~(n(i)==1||m(i)==1))
    if(x1(m(i)-1)==x2(n(i)-1))
        n(i+1)=n(i)-1;
        m(i+1)=m(i)-1;
        i=i+1;
        continue;
    end
    c=H(n(i)-1,m(i)-1);
    if(c<H(n(i),m(i)-1)&&H(n(i),m(i)-1)>=H(n(i)-1,m(i)))
        n(i+1)=n(i);
        m(i+1)=m(i)-1;
    elseif(H(n(i)-1,m(i))>c&&H(n(i)-1,m(i))>H(n(i),m(i)-1))
        n(i+1)=n(i)-1;
        m(i+1)=m(i);
    else
        n(i+1)=n(i)-1;
        m(i+1)=m(i)-1;
    end
    
    i=i+1;
end
n=n(1:end-1);
m=m(1:end-1);
for i=1:length(n)
    if(H(n(1,i),m(1,i))==0)
        n(2,i)=1;
        m(2,i)=1;
    else
        n(2,i)=0;
        m(2,i)=0;
    end
end
n2=n(1,find(n(2,:)==0))-1;
m2=m(1,find(m(2,:)==0))-1;
for i=length(n2):-1:1
    A(-i+length(n2)+1)=x1(m2(i));
    B(-i+length(n2)+1)=x2(n2(i));
    if(i~=length(n2))
        if(n2(i+1)==n2(i))
            B(-i+length(n2)+1)='_';
        elseif(m2(i+1)==m2(i))
            A(-i+length(n2)+1)='_';
        end
    end
end
X1(1)=string(num2str(0));
x11='abcdefghlmn';
for i=1:length(x1)
    X1(i+1)=strcat(x1(i),x11(i));
end
X2(1)=string(num2str(0));

for i=1:length(x2)
    X2(i+1)=strcat(x2(i),x11(i));
end

h=heatmap(X1,X2,H);
set(h,'Position',[0.1,0.1,0.7,0.8]);
colormap(cool);
for i=1:length(n2)-1
    annotation('arrow',[0.7*(m2(i)+0.5)/(length(x1)+1)+0.1,0.7*(m2(i+1)+0.5)/(length(x1)+1)+0.1],[0.8*(length(x2)+0.5-n2(i))/(length(x2)+1)+0.1,0.8*(length(x2)+0.5-n2(i+1))/(length(x2)+1)+0.1],'Color','w');
end
disp('比对结果为:');
disp(A);
disp(B);











        

4.结果

  • 6
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Smith-Waterman算法是一种用于序列比对的动态规划算法。它可以用于比对DNA、RNA、蛋白质序列等。C++是一种高效的编程语言,可以用于实现Smith-Waterman算法实现Smith-Waterman算法的C++代码需要考虑以下几个方面: 1. 输入序列:需要从文件或者用户输入中读取待比对的序列。 2. 动态规划矩阵:需要创建一个二维数组来存储动态规划矩阵。 3. 算法实现:需要实现算法的核心部分,包括初始化矩阵、计算得分、回溯路径等。 4. 输出结果:需要将比对结果输出到文件或者屏幕上。 以下是一个简单的Smith-Waterman算法的C++实现示例: ```c++ #include <iostream> #include <fstream> #include <cstring> using namespace std; const int MAXLEN = 1000; const int GAP = -2; const int MATCH = 3; const int MISMATCH = -1; int score[MAXLEN][MAXLEN]; int max(int a, int b, int c) { int m = a; if (b > m) m = b; if (c > m) m = c; return m; } void init(int n, int m) { for (int i = 0; i <= n; i++) { score[i][0] = 0; } for (int j = 0; j <= m; j++) { score[0][j] = 0; } } void compute_score(char* s1, char* s2, int n, int m) { for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { int match = score[i-1][j-1] + (s1[i-1] == s2[j-1] ? MATCH : MISMATCH); int delete_gap = score[i-1][j] + GAP; int insert_gap = score[i][j-1] + GAP; score[i][j] = max(match, delete_gap, insert_gap); } } } void traceback(char* s1, char* s2, int n, int m) { int i = n, j = m; while (i > 0 && j > 0) { int match = score[i-1][j-1] + (s1[i-1] == s2[j-1] ? MATCH : MISMATCH); int delete_gap = score[i-1][j] + GAP; int insert_gap = score[i][j-1] + GAP; if (score[i][j] == match) { cout << s1[i-1] << " " << s2[j-1] << endl; i--; j--; } else if (score[i][j] == delete_gap) { cout << s1[i-1] << " -" << endl; i--; } else { cout << "- " << s2[j-1] << endl; j--; } } } int main() { char s1[MAXLEN], s2[MAXLEN]; cin >> s1 >> s2; int n = strlen(s1), m = strlen(s2); init(n, m); compute_score(s1, s2, n, m); traceback(s1, s2, n, m); return 0; } ``` 该示例代码实现Smith-Waterman算法的核心部分,包括初始化矩阵、计算得分、回溯路径等。在输入两个待比对的序列后,程序会输出比对结果。需要注意的是,该示例代码只是一个简单的实现,实际应用中可能需要进行更多的优化和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

从零开始的奋豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值