3.15周末学长教了一下KMP,但是对next的构造尚存疑.在饶了一整天头以后勉强弄懂了…记录一下比较混乱就是了…
将next数组记录的值看作是对称程度
这里的对称指的的字符块对称而非轴对称;
--------->当next[t]值为0时:
显然就意味着从字符串的开头到这个t部分的话对称性是0:即当继续计算下一位的next[t+1] 的大小时只需比较第n+1位的字符与首字符是否相同即可
--------->当next[t]值不为0时:
这个时候就说明从字符串的开头到这个t部分的话存在对称字符我们假设next[t]的值是a,那么就说明前a个字符与后a个字符是相同的.我们计算next[t+1]时就只需要比较第a+1的字符与t+1的字符是否一致
- 当这两个字符相同时,显然,我们只需要令next[t+1]=next[t]+1即可
- 当这两个字符不相同时
这里先放一个大佬码的完整代码
void makeNext(const char P[],int next[])
{
int q,k;//q:模版字符串下标;k:最大前后缀长度
int m = strlen(P);//模版字符串长度
next[0] = 0;//模版字符串的第一个字符的最大前后缀长度为0
for (q = 1,k = 0; q < m; ++q)//for循环,从第二个字符开始,依次计算每一个字符对应的next值
{
while(k > 0 && P[q] != P[k])//递归的求出P[0]···P[q]的最大的相同的前后缀长度k
k = next[k-1]; //不理解没关系看下面的分析,这个while循环是整段代码的精髓所在,确实不好理解
if (P[q] == P[k])//如果相等,那么最大相同前后缀长度加111
{
k++;
}
next[q] = k;
}
}
相当于就是解释一下这段语句的含义
先看这几个字母的定义
k:最大相同前后缀长度
P:输入的要建next数组的字符串
q:要建立next数组的下标
while(k > 0 && P[q] != P[k]):
这个很好理解,注意一下这个时候的k在没有进行while循环时存储的是在q-1个字符中的最大相同前后缀
意思就是如果没有相同的前后缀了或者第k+1(因为next是从o开始建的)和第q个相同时我们就跳出
然后我们来分析一下:k = next[k-1];
这段代码可以说是核心了
首先要进行这段语句的前提:
k > 0 && P[q] != P[k].首先要尚存相同的前后缀,如果已经没有相同前后缀时,直接跳出给next[q]赋0就ok.并且P[q] != P[k].
紧接着看这个语句的意义:,我们仍然从第一次进入while循环分析:
这里k本来是指q之前的字符串最大前后缀长度,因为第q个字符和第k+1个字符不相同,我们再继续找这最大前后缀长度包括的最大的前后缀长度,并且这样循环的比较下去.知道发现能构成一个新的最大前后缀长度或者是干脆构不成.