理解递归(推)求解next数组的代码是个难点,对于刚入门来说
next数组求解的时候是 已知next[0....j],next[j]=k.求解next[j+1]
首先next[j]=k的含义是说前j-1个字符最长相同前后缀是k,也说明前缀的最后一个字符下标是k-1
如果p[j]==p[k],那很明显是next[j+1]=k+1;
p[j]!=p[k]时,这时候
关键记住一句话:模式串的自我匹配
比如ADAC和ABAD
在C、D比较时候,失配了,是不是把ABAD往前移动 j-next[j] 等价于
也就是把 p[next[j]](在这里是p[1]也就是D)和当前字符D比较
那么模式串 ADACADADFGH 在计算 ADACADAD 最长相同前后缀是多少
当发现C、D失配
此时就相当于 ADAC和ADAD作匹配
也就是如下过程
C位置的next是1(ADA),也就是拿ADAC中的D来和 ADAD作匹配
此时p[next[k]==p[j] 然后next=k+1=1+1=2
k=next[k]相当于KMP算法中的j-next[j],一个是“显式”移动,一个是直接改变p[k]中的下标,本质相同
代码如下
void GetNext(char* p,int next[])
{
int pLen = strlen(p);
next[0] = -1;
int k = next[0];
int j = 0;
while (j < pLen - 1)
{
//p[k]表示前缀,p[j]表示后缀
if (k == -1 || p[j] == p[k])
{
//++k;
//++j;
//next[j] = k;
next[j+1] = k+1;
k++;j++;
}
else
{
k = next[k];
}
}
}
说白了,你不和我相配,我再递归找你前面有没有相同前缀后缀,一直找到next[0]=-1为止,此时next[j]=k+1=-1+1=0