kmp算法——深入理解next数组

285 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情


求next数组是kmp算法中不可或缺的一步,以next[i]为例,其具体含义为str[1~i]中前缀与后缀能匹配的最长长度。注意这里的前后缀不能是整个字符串,不然的话所有的next[i]都等于i了,没有意义。还有这里的next[i]只是最长的长度,比它小的长度有没有匹配并不确定。

求next数组的模板:

for(int i = 2, j = 0; i <= len; i++)
{
	while(j && s[j+1] != s[i])
		j = _next[j];
	if(s[j+1] == s[i])
		j++;
	_next[i] = j;
}

目前发现的关于next的有意思的用法:

  1. 求str[1~len]中所有匹配的前后缀

    证明很简单,画图推一下就行,直接上代码。

    int t = _next[len];
    while(t >= 1)//直到t=0 
    {
            cnt++;//记录能匹配的前后缀数量 
            t = _next[t]; 
    }
    
  2. 求某个前缀在串中出现(可重叠)次数

    结合dp,其中dp[i]表示str[1~i]在整个串出现次数。显然是个刷表的过程,倒序遍历是为了保证使用到dp[i]时它已经被更新完毕。逻辑上也很好理解,对于每一次出现的str1~i都会使dp[next[i]]增加1。

    for(int i = 1; i <= len; i++)
            dp[i]++;
    for(int i = len; i >= 1; i--)
            dp[_next[i]] += dp[i];