KMP算法及其优化

KMP算法

时间复杂度O(n + m)

NFA:不确定性有穷状态自动机

在这里插入图片描述

int *getNext(const char *t, int *len){
    *len = strlen(t);
    int *next = (int *) malloc (sizeof(int) * (*len)); // next[i] = j : 以i位置结尾,所匹配到的最长前缀是j这个 位置
    next[0] = -1; //匹配最长前缀不能包含自己,第一位的最长前缀为-1
    for(int i = 1, j = -1; t[i]; i++){
        //i是当前匹配的位置,j是i的前一位能匹配到的最长前缀的位置。所以i与j+1比较
        while(j != -1 && t[j + 1] != t[i]) j = next[j]; //匹配不成功就往前找
        if(t[j + 1] == t[i]) ++j; //匹配成功就按照i-1位置最长前缀的数量+1
        next[i] = j;//更新next数组
    }

    return next;
}

int kmp(const char *s, const char *t){
    int len = 0;
    int *next = getNext(t, &len); //初始化next数组
    //j代表之前成功匹配过的模式串在第几位
    for(int i = 0, j = -1; s[i]; i++){ 
        while(j != -1 && t[j + 1] != s[i]) j = next[j]; //NFA(不确定性)
        if(t[j + 1] == s[i]) ++j;
        if(t[j + 1] == '\0') { //完全成功匹配了模式串
            free(next);
            return i - len + 1;
        }
    }
    free(next);
    return -1;
}

KMP的优化:

DFA:确定性有穷状态自动机
在这里插入图片描述

void free_next(int *next){
    free(next);
    return ;
}

void free_jump(int **jump, int len){
    for(int i = 0; i < len; i++) free(jump[i - 1]);
    free(jump - 1);
    return ;
}

//获取跳转信息的数组
int **getJump(int *next, const char *t, int n){
    int **jump = (int **) malloc(sizeof(int *) * n);
    for(int i = 0; i < n; i++) jump[i] = (int *) malloc(sizeof(int) * 26);
    ++jump; //让jump指向next数组1的位置,使它访问-1位置的时候实际上访问的是0,合法的
    for(int i = 0; i < 26; i++) jump[-1][i] = -1;
    jump[-1][t[0] - 'a'] = 0; //模式串的第一个字符
    for(int i = 0, I = n - 1; i < I; i++){
        for(int j = 0; j < 26; j++) jump[i][j] = jump[next[i]][j];
        jump[i][t[i + 1] - 'a'] = i + 1;
    }
    return jump;
}

//Kmp的优化算法
int kmp_opt(const char *s, const char *t){
    int len = 0;
    int *next = getNext(t, &len);
    int **jump = getJump(next, t, len); 
    //j代表之前成功匹配过的模式串在第几位
    for(int i = 0, j = -1; s[i]; i++){ 
        j = jump[j][s[i] - 'a']; //DFA(确定性)
        if(j == len - 1){ //已找到字符串
            free_next(next);
            free_jump(jump, len);
            return i - len + 1;
        }
    }
    free_next(next);
    free_jump(jump, len);
    return -1;
}

字符串匹配算法合集:
六种字符串匹配算法详解

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是KMP算法及其改进算法优化next数组)的C语言实现: KMP算法: ```c void getNext(char *pattern, int *next) { int i = 0, j = -1; next[0] = -1; while (pattern[i]) { if (j == -1 || pattern[i] == pattern[j]) { i++; j++; next[i] = j; } else { j = next[j]; } } } int KMP(char *text, char *pattern) { int i = 0, j = 0; int text_len = strlen(text); int pattern_len = strlen(pattern); int *next = (int *)malloc(sizeof(int) * pattern_len); getNext(pattern, next); while (i < text_len && j < pattern_len) { if (j == -1 || text[i] == pattern[j]) { i++; j++; } else { j = next[j]; } } free(next); if (j == pattern_len) { return i - j; } else { return -1; } } ``` 改进算法优化next数组): ```c void getOptimizedNext(char *pattern, int *next) { int i = 0, j = -1; next[0] = -1; while (pattern[i]) { if (j == -1 || pattern[i] == pattern[j]) { i++; j++; if (pattern[i] != pattern[j]) { next[i] = j; } else { next[i] = next[j]; } } else { j = next[j]; } } } int KMP_Optimized(char *text, char *pattern) { int i = 0, j = 0; int text_len = strlen(text); int pattern_len = strlen(pattern); int *next = (int *)malloc(sizeof(int) * pattern_len); getOptimizedNext(pattern, next); while (i < text_len && j < pattern_len) { if (j == -1 || text[i] == pattern[j]) { i++; j++; } else { j = next[j]; } } free(next); if (j == pattern_len) { return i - j; } else { return -1; } } ``` 在上面的示例代码中,KMP算法中的getNext函数用来计算next数组,KMP函数用来执行KMP算法的主体部分。改进算法中的getOptimizedNext函数用来计算优化后的next数组,KMP_Optimized函数用来执行优化后的KMP算法。这些函数可以根据需要修改函数参数和返回值类型以适应实际情况。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值