长字符串匹配(BWT编码、后缀数组、倍增算法、FM索引)

用 O(m) 时间复杂度找出一个长度为 m 的短字符串在一个长度为 n 的长字符串中的精确匹配(n>>m),限制长短字符串仅由 A、C、G、T 这四种字符组成。

输入:长短字符串

输出:短字符串在长字符串里的精确匹配


​在匹配前先对长串进行编码和索引计算的预处理,该部分用到BWT编码的思想,并且利用后缀数组和倍增算法对编码过程进行优化。由于长串过长,在编码和存储时对其进行分治处理,并且在索引存储时进行优化,对索引进行间隔存储。在匹配时,用预处理得到的长串编码和索引进行匹配,用到的是FM索引-序列匹配。


BWT编码和索引计算

BWT的全称是The Burrows-Wheeler Transform,也就是所谓的轮转排序。在字符串匹配中首先用BWT对长字符串S进行预处理,得到编码结果BWT(S)和相应索引,用于后续FM索引技术对字符串进行匹配。

BWT编码对应具体步骤如下:

​ 1、设需要编码的长字符串为S,在S末尾加上标记字符 $(该字符的字典序值小于长串中所有字符),得到新字符串S‘,记S’的长度为 len 。

​ 2、对S’进行循环移位,每次将S’中的最后一个字符转移到整个字符串的最前面,一共转移 len 次,每次转移都得到一个长度为 len 的新字符串。

​ 3、把上一步中得到的 len 个新字符串按照字典序排序,得到一个 len × len 的字符矩阵M。

​ 4、M中每个字符串的第一个字符构成 F 列,最后一个字符构成 L 列。L 列即为BWT(S)。


BWT编码示例

BWT编码示例

通常为了节省空间,M 中各行字符串只保留 $ 之前的部分,也就得到所谓的后缀字符串组 Suffix,Suffix 中每一行的字符串都是 S’ 的一个后缀。

在这里插入图片描述

后缀字符串组示例

在求BWT(S)的过程中,需要同时建立索引,以节省后续字符串匹配时间。由于该问题中用到的长串和短串只包含 A、C、G、T 这四种字符,因此建立的索引主要这样三个部分:

​ 1、num_a , num_c , num_g , num_t:分别记录A、C、G、T 在 S 中出现的次数

​ 2、后缀数组SA:SA[i]表示后缀字符串组Suffix里的第 i 个字符串的起始字符在 S’ 中的下标,即F[i]在 S’ 中的下标。

​ 3、count_num[char][row]count_num[0][i]表示到L[i - 1]为止, A 出现过的次数;count_num[1][i]表示到L[i - 1]为止, C 出现过的次数,以此类推。即若L[i]处的字符为 A,则要用当前 A 的计数将count_num[0][i]的值赋完后才对 A 的计数+1,也就表示在 L 里的所有字符 A 中,L[i]处的字符 A 的排序(该排序从0开始)。
在这里插入图片描述

索引计算示例

根据上述BWT算法的处理步骤,对 S 进行BWT编码和计算索引的过程对应下述代码操作:

//轮转和排序
vector<string>M(len);
for(int i = 0; i < len; i++) {
   
    string new_s(i + 1, ' ');
    for(int j = 0; j < i + 1; j++)
        new_s[j] = S[len - 1 - i + j];
    M[i] = new_s;
}
sort(M.begin(), M.end());

//得到BWT(S)和编码
string L(len, ' ');
for(int i = 0; i < M.size(); i++) {
   
	SA[i] = len - M[i].size();
    if(SA[i] == 0)
		L[i] = '$';
    else {
   
		L[i] = S[SA[i] - 1];
		count_num[0][i] = num_a;
		count_num[1][i] = num_c;
		count_num[2][i] = num_g;
		count_num[3][i] = num_t;

		if
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值