KMP的第n次学习笔记

关于字符串的下标:

建议都用从0开始的下标。

给谁算next数组?

给模式串(Pattern)算next数组。KMP保证的是母串(Text)一个一个字符来的时候永不后退,但模式串的位置是要经常变化的。千万不要去给Text串算next数组……

即:应该是给pattern串构建自动机,而不是text串。text串要在这个自动机上运行。

关于next数组:

真正编程的时候,next数组并不是“长度为len的前缀和长度为len的后缀相等”的len。事实上,这个len数组有另外一个名字,比如叫Partial Match Table(PMT);next是这个数组往后错了一位。
例如Pattern串是aabaabaac, 那么PMT =[0, 1, 0, 1, 2, 3, 4, 5, 0], next是这个数组整体往右错了一位,即[-1, 0, 1, 0, 1, 2, 3, 4, 5]。
PMT和next示意图
(图片来自:https://www.zhihu.com/question/21923021
next数组的第一个数值永远是-1,这纯粹是为了写起来方便,因为-1+1=0,正好可以对应到字符串的第一个元素。next数组的第一个元素是没有物理意义的。

Coding

写程序的时候,也没有必要特意的注意+1或者-1。因为比如发现T[i] != P[j],那么next[j]已经告诉你j-1位置结束的那个子串前后缀有多少相等了,所以你就听next[j]的就可以了。
抄一段上面知乎回答当中的code:

int KMP(char * t, char * p) 
{
    int i = 0; 
    int j = 0;

    while (i < strlen(t) && j < strlen(p))
    {
        if (j == -1 || t[i] == p[j]) 
        {
            // j==-1时,说明当前t的这个字符根本没戏了,所以弃疗吧,i++就去看text串的下一个字符了
            // 注意j==-1时,j+1=0,正好就是pattern串的第一个字符,即是text串的下一个字符和pattern串的第一个字符马上就要比对了
            i++;
            j++;
        }
        else 
            // 听pattern串自己的next数组,减小pattern串指针j,本质上是前移pattern串
            j = next[j];
    }

    if (j == strlen(p))
       return i - j;
    else 
       return -1;
}

作者:海纳
链接:https://www.zhihu.com/question/21923021/answer/281346746
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

怎么求next

一样的道理,注意后增加i,因为next数组是错开一位的,所以每次i指的是当前的字符,但是要i+1以后再填充next值。
所谓“自我匹配”,实际上是当前到位置i的时候和位置j做匹配。比如上图i到c的时候,j到b的位置,所以恰好错了一位。永远要把j的位置理解成一个自动机就好办了。

void getNext(char * p, int * next)
{
    next[0] = -1;
    int i = 0, j = -1;

    while (i < strlen(p))
    {
        if (j == -1 || p[i] == p[j])
        {
            ++i;
            ++j;
            next[i] = j;
        }   
        else
            j = next[j];
    }
}

作者:海纳
链接:https://www.zhihu.com/question/21923021/answer/281346746
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值