数据结构与算法-KMP算法

169 阅读2分钟

继续讨论字符串匹配问题关于KMP算法的实现 juejin.cn/post/684490… KMP主要是利用一个数组回溯索引路径,我们用2层循环对比主字符串S位置i 与模式串T位置j 的字符对比

首先我们要生成一个next数组来存储对应的j需要回溯的位置

//----KMP 模式匹配算法---
//1.通过计算返回子串T的next数组;
void getNext(String T, int* next ){
    // 注意 字符串从T[1] 开始 T[0] 为字符串长度
    int j = 1;
    int i = 0;
    next[1] = 0;
    //遍历T模式串, 此时T[0]为模式串T的长度;
    //printf("length = %d\n",T[0]);
    while (j < T[0]) {
        //printf("i = %d j = %d\n",i,j);
        if(i ==0 || T[i] == T[j]){
            //T[i] 表示后缀的单个字符;
            //T[j] 表示前缀的单个字符;
             i++;j++;
            next[j] = i;
        }else
        {
            //如果字符不相同,则i值回溯;
            i = next[i];
        }
    }
    
}


//----KMP 模式匹配算法---
//1.通过计算返回子串T的next数组;
//注意字符串T[0]中是存储的字符串长度; 真正的字符内容从T[1]开始;
void get_next(String T,int *next)


int count = 0;
//KMP 匹配算法(1)
//返回子串T在主串S中第pos个字符之后的位置, 如不存在则返回0;
int Index_KMP(String S,String T,int pos){
    
    //i 是主串当前位置的下标准,j是模式串当前位置的下标准
    int i = pos;
    int j = 1;
    
    //定义一个空的next数组;
    int next[MAXSIZE];
    for (i=0; i<MAXSIZE+1; i++) {
        next[i] = 0;
        
    }
     NextPrint(next,MAXSIZE);
    //对T串进行分析,得到next数组;
    getNext(T, next);

    for (int i =0; i<T[0]; i++) {
        printf("%d",next[i]);
    }
      printf("next数组的值 \n");
    
    count = 0;
    //注意: T[0] 和 S[0] 存储的是字符串T与字符串S的长度;
    //若i小于S长度并且j小于T的长度是循环继续;
    while (i <= S[0] && j <= T[0]) {
        
        //如果两字母相等则继续,并且j++,i++
        if(j == 0 || S[i] == T[j]){
            i++;
            j++;
            
            printf("%d 对比 %d \n",S[i],T[j]);
        }else{
            //如果不匹配时,j回退到合适的位置,i值不变;
            j= next[j];
            printf("不匹配 %d \n",j);
        }
    }
    
    if (j > T[0]) {
        return i-T[0];
    }else{
        return -1;
    }
    
}


//输出Next数组值
void NextPrint(int next[],int length)
{
    int i;
    for(i=1;i<=length;i++)
        printf("%d",next[i]);
    printf("\n");
}