序列比对(26)精准匹配之KMP算法、Trie树以及AC自动机

前文已经介绍过KMP算法和Trie树,本文将在此基础上介绍AC自动机。

(公众号:生信了)

之前的序列比对文章大都在利用动态规划算法解决字符串的非精准匹配(允许错配、插入和缺失),比如全局比对和局部比对问题。当然,后来我们还介绍了模序发现和中间字符串问题,并初次学习了如何用分支定界法解决这一类问题。

既然有非精准匹配问题,就有精准匹配问题。所谓精准匹配,就是两个字符串在比对时,不允许错配、插入和缺失。其实,笔者之前已经有过介绍:

KMP算法

《算法(四)(转载)KMP算法》一文介绍了KMP算法,该算法常用来解决如何在一个长字符串(模板串)中寻找一个短字符串(模式串)的问题。其特点就是要预先对模式串进行处理,对其构建一个next数组,该数组中存放着模式串每一个位置所对应的跳转指针,这样做的效果是模板串的指针不用回溯,一直在递增,从而增加效率。

KMP算法的完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 1000

void getNext(const char *pat, int *next, const int n) {
   
/* assume n >= 2 */
    int i, j;
    for (next[0] = -1, next[1] = 0, i = 1, j = 0; i < n - 1;) {
   
        while (j != -1 && pat[i] != pat[j])
            j = next[j];
        next[++i] = ++j;
    }
}

int KMP(const char *temp, const int m, const char *pat, const int n) {
   
    int i, j;
    int *next = (int*) malloc(sizeof(int) * n);
    getNext(pat, next, n);
    for (i = 0, j = 0; i < m && j < n;) {
   
        if (j == -1 || temp[i] == pat[j]) {
   
            i++;
            j++;
        } else {
   
            j = next[j];
        }
    }
    free(next);
    if (j < n)
        return -1;
    return i - j;
}

int main(void) {
   
    char t[MAXLEN], p[MAXLEN];
    int index;
    printf("the temp str: ");
    scanf("%s", t);
    printf("the pattern str: ");
    scanf("%s", p);
    if ((index = KMP(t, strlen(t), p, strlen(p))) == -1)
        printf("Not found!\n");
    else
        printf("Index is %d.\n", index);
    return 0;
} 

其效果如下:
在这里插入图片描述

Trie树(字典树)

《算法(五)字典树算法快速查找单词前缀》一文介绍了Trie树,该算法常用来解决如何在多个模板串中寻找一个模式串的问题。其特点就是将多个模板串装填进一个树结构中,虽然使用了较多的空间,但是查找效率得到了提升。

Trie树的完整代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 26
#define MAXLEN 1000

struct Node {
   
    struct Node *a[N];
    int is_end;
};
typedef struct Node *tnode;

tnode init() {
   
    tnode p;
    int i;
    if ((p = (tnode) malloc(sizeof(struct Node))) == NULL) {
   
        fputs("Error: out of space!\n", stderr);
        exit(1);
    }
    for (i = 0; i < N; i++)
        p->a[i] 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值