KMP算法

1、总结

切记:书上过程是下标从1开始的。不要纠结next数组第一位为什么是0。(DP也不纠结边界为啥是0啊。。。)。

  1.  完整过程:
    1. 求PM[]。(部分匹配表)
    2. 求move[]。(要移动的位数)
    3. 求next[]。(子串中移动后的下标)
  2. 简化过程:
    1. 求PM[]。
    2. 右移1位
    3. 加1(下标从1开始要加,下标从0开始不用加)
  3. 优化后的KMP
    1. 看程序,一步一步算。主串在后面,子串在前面。

2、代码

String数据结构

//串的堆分配存储结构(malloc()占用的是堆空间)
//下标为0的位置不用
typedef struct
{
    char *ch;   //若是非空串,则按串长分配存储区;否则ch为NULL
    int length; //串长度
}HString;
typedef HString String;

2.1 计算next数组(下标从1开始)

//计算next数组
void get_next(String T, int next[])
{
    int i = 1, j = 0;
    next[1] = 0;
    while (i < T.length) // i遍历串中的每个字符(主串)
    {
        if (j == 0 || T.ch[i] == T.ch[j]) //子串第一个元素失配||主串与子串指针处字符相同
        {
            ++i;
            ++j;
            next[i] = j;
            // 1 子串第一个元素失配:主串下标为i的元素next值为1(next[i]=1)
            // 1 第二次进while若还是子串第一个元素失配,则j=next[1]=0
            // 1 第三次进while时执行与第一次进while时相同的操作:next[i]=1
            // 2 主串i与子串j处字符相同:主串下标为i的元素next值为j+1
        }
        else //主串i与子串j处字符失配,且j不为0(j为1时来过渡一下)
            j = next[j];
    }
}

2.2 计算next数组(下标从0开始)

//计算next数组,下标0开始
void get_next_0(String T, int next[])
{
    int i = 0, j = -1;
    next[0] = -1;
    while (i < T.length)
    {
        if (j == -1 || T.ch[i] == T.ch[j])
            next[++i] = ++j;
        else
            j = next[j];
    }
}

2.3 计算nextval数组(求next数组优化版)

//计算next数组-优化
void get_nextval(String T, int nextval[])
{
    int i = 1, j = 0;
    nextval[1] = 0;
    while (i < T.length) // i遍历串中的每个字符(主串)
    {
        if (j == 0 || T.ch[i] == T.ch[j]) //子串第一个元素失配||主串与子串指针处字符相同
        {
            ++i;
            ++j;
            if (T.ch[i] != T.ch[j]) // i++,j++后,串与子串指针处字符不相同
                nextval[i] = j;
            else //主串与子串有连续两个字符相等
                nextval[i] = nextval[j];
        }
        else //主串i与子串j处字符失配,且j不为0(j为1时来过渡一下)
            j = nextval[j];
    }
}

 

posted @ 2023-02-01 20:34  尚方咸鱼  阅读(36)  评论(0编辑  收藏  举报