其实我一直都没有理解严老师的数据结构中对于next函数求法中的一句话
next 函数求值可以看作是串的模式匹配问题,这句话我一直我不是很理解,我一直把它的过程理解为一个动态规划的过程(有兴趣的话可以参见上一篇文章),后来学长做的一个软件让我明白了
开始的时候,将t串的第一个字母的next值作为0,因为他没有前缀,第二个也是没有后缀,所以他一定是1,但是不能直接将其赋值为1,因为的直接影响着下一个的递推算值,如果相等就i++,j++next[i]=j了,从第三个值开始它就有前缀和后缀了(注意,next[3]函数的意思不是求最大2~3个的后缀等于哪个前缀,而是最大2~2个的最大后缀)所以next[10]=9;
把next的值看作模式匹配问题时候,下面的t串相当于前缀,而上面的t串相当于后缀。
言归正传,我们来谈论,求最小循环串的问题。
我们设想,我们可以利用next函数来求最小循环子串,我们看图
当有循环节的时候,他会有大量的重合,从图中可以看出strlen(T)-j<strlen(T)/2,strlen(T)-j达到最大时候就是只循环两次的时候,就是strlen(T)-j=strlen(T)/2
而没有循环节时候,他的最后strlen(T)-j大于strlen(T)/2,最小的时候就是两次循环的时候
所以,我们以strlen(T)%(strlen(T)-j)是否是0来判断是否是有循环节,然后又用strlen(T)/(strlen(T)-j)来求出最小循环节的大小。
但是细心的读者会发现我们是从0开始的,这样strlen(T)会多一个,并且如果单纯的减1,会因为不符合常理(取余操作过不去)而被判断为没有循环节,所以,我们让j在走一步,这个意思是说到达最后一个的时候,我们不让他返回next[strlen(T)-1]而是返回最后一个j,这样如果最后一个符合条件就会next[strlen(T)-1]++,如果最后一个不符合就会返回next[j],这样不仅解决了strlen(T)的问题,而且解决了只循环两次的问题,例如
这样会返回next[4],也解决了只循环两次的问题。