KMP算法

378 阅读2分钟
  • 了解KMP

    要了解KMP算法主要要了解next数组的生成以及回溯位置的依据,这个还是很绕的,在写这个博客的时候都把自己绕进去好几回,所以建议看一遍有点迷糊的多看几遍,也可以在评论区一起讨论一下
  • 图解KMP算法过程

  • next数组推导

/**
 KMP算法next数组实现
 next数据记载着模式串回溯的位置
 */
int * get_Next(char *model){
    int *next;
    int len = (int)strlen(model);
    next = (int *)malloc(sizeof(int) * strlen(model));
    if(len <= 0) return next;
    //默认第0个位置的回溯位置为0
    next[0] = -1;
    for(int i = 1; i < len; i++){
        if(i == 1){
            //当i=1的前面只有一个字符所以直接将回溯位置置位0
            next[i] = 0;
        }else{
            //否则找出前缀和后缀是否相等、有几个元素相等,对应求出回溯位置
            if(model[i-1] == model[next[i-1]]){
                next[i] = next[i-1] + 1;
            }else{
                next[i] = 0;
            }
        }
    }
    return next;
}
  • next数组优化

/**
 next数组优化
 */
int * get_Next2(char *model){
    int *next;
    int len = (int)strlen(model);
    next = (int *)malloc(sizeof(int) * strlen(model));
    if(len <= 0) return next;
    //默认第0个位置的回溯位置为0
    next[0] = -1;
    for(int i = 1; i < len; i++){
        if(i == 1){
            //当i=1的前面只有一个字符所以直接将回溯位置置位0
            next[i] = 0;
        }else{
            //否则找出前缀和后缀是否相等、有几个元素相等,对应求出回溯位置
            if(model[i-1] == model[next[i-1]]){
                next[i] = next[i-1] + 1;
            }else{
                next[i] = 0;
            }
        }
    }
    for(int i = 1; i < len; i++){
        //回溯位置优化
        while (next[i] != -1 && model[i] == model[next[i]]) {
            next[i] = next[next[i]];
        }
    }
    return next;
}
  • 代码实现

/**
 KMP算法
 */
int kmp(char *str,char *model){
    if(strlen(model) <= 0) return -1;
    if(strlen(str) <= 0) return -1;
    int *next = get_Next2(model);
    int i = 0;
    int j = 0;
    while (i < strlen(str) && j < (int)strlen(model)) {
        if(j == -1 || str[i] == model[j]){
            i++;
            j++;
        }else{
            j = next[j];
        }
    }
    if(j >= (int)strlen(model)){
        return i-j + 1;
    }
    return -1;
}