KMP算法

作者: XGamer | 来源:发表于2020-09-09 21:54 被阅读0次

    void GetNextval(string partStr, vector<int>& nextval)

    {

    int p_len = partStr.size();

    //由 next[i] = j 得,也就是对于位置 i 来说,

    //区段[0, i - 1] 的最长相同真前后缀分别是[0, j - 1] 和[i - j, i - 1],即这两区段内容相同。

    int i = 0;  // P 的下标

    int j = -1;

    nextval[0] = -1;

    while (i < p_len)

    {

    //  j == -1 存在的意义是何?

    //  第一,程序刚运行时,j 是被初始为 -1,直接进行 P[i] == P[j] 判断无疑会边界溢出;

    // 第二,else 语句中 j = next[j],j 是不断后退的,若 j 在后退中被赋值为 -1(也就是 j = next[0]),在 P[i] == P[j] 判断也会边界溢出。

    // 综上两点,其意义就是为了特殊边界判断。

    if (j == -1 || partStr[i] == partStr[j])

    {

    i++;

    j++;

    nextval[i] = j;

    //为了防止出现ABCDAB 若在 i = 5 时匹配失败,此时应该把 i = 1 处的字符拿过来继续比较,

    //但是这两个位置的字符是一样的,都是 B,既然一样,拿过来比较不就是无用功了么?

    //所以将nextval[i] = j;优化,如果相同就继续往前找前缀

    if (partStr[i] != partStr[j])

    nextval[i] = j;

    else

    nextval[i] = nextval[j];  // 既然相同就继续往前找真前缀

    }

    else

    j = nextval[j];

    }

    }

    int  KMP(string mianStr, string partStr) {

    int partLen = partStr.length();

    vector<int> nextList(partLen+1,0);

    GetNextval(partStr, nextList);

    int i = 0;

    int j = 0;

    while (i < mianStr.length()&& j < partLen)

    {

    if (j==-1|| mianStr[i] == partStr[j])

    {

    i++;

    j++;

    }

    else

    {

    j = nextList[j];

    }

    }

    if (j == partLen)

    {

    return i - j;

    }

    return -1;

    }

    相关文章

      网友评论

          本文标题:KMP算法

          本文链接:https://www.haomeiwen.com/subject/lwbyektx.html