纯属个人观点,供自己学习用,无参考价值,千万不要拿来学习!!!
花了两个小时的时间去研究了一下kmp算法以及代码实现,可是看完之后还是对next数组求法有点蒙圈。
先把next数组的代码贴上来:
void getnext(char *p,int *next){
next[0]=-1;
int i=0,j=-1;
while(i<strlen(p)-1){
if(j==-1||p[j]==p[i]){
i++;
j++;
next[i]=j;
}
else j=next[j];
}
}
next[0]等于负一,是因为我们第i个位置的next值是前i-1个字符的pmt值。
对于j的理解,我们可以将它理解成一个指针,它指在模式串的第j个位置。在这个匹配过程中,如果j=3时候依然匹配成功,那么这个模式串的前四个字符都是匹配成功的,也就是说此时前i个字符中前缀和后缀的最大交集pmt为j+1,那么我们将i和j自增之后赋给此时i的next值。
对于j=next[j],我看很多人是从递归的角度理解,但我更愿意从对称(?)的角度去理解。
比如对于这样一个伪对称的字符串:
ABDAB CD ABDAB DE
ABDAB CD ABDAB DE
AB DAB CD ABDAB DE
从这里我们可以看到,他在j=5的时候不匹配了。那么我们是跳到开头寻找?显然不是。j=5前面的子串的最大后缀AB明显有个最大前缀AB对应,那么我们只需要跳到最大前缀后一个位置,判断该位置的字符是否为D,如果是,匹配成功,i+1的位置赋值3即可。
那如果继续匹配不成功呢?我们就需要在这个位置前面的j个字符中继续寻找,直到这个位置的next值为0,就是说前面的字符串不再具有对称性,也就是说对于这个字符前面字符串的任意一个后缀,你都找不到前缀和他对应,j此时就跳到-1了。
说了这么多,j=-1到底是啥呢?(这个还真不太好描述。。。)
经过严谨(x)的思考,我想把j=-1称为一个启动状态。每当j=-1的时候,我们就知道下一个位置的next值就应该为0了(具体为啥不再赘述)。