问题1
关于ans=len-next[len]中,ans为最小循环节这个结论百思不得其解,看了几个博客后感觉稍微有一些领悟
博客
思想
首先next数组的含义:next[i]表示前面长度为i的子串中,前缀和后缀相等的最大长度
接着我们抛开一切概念,直接分情况直接讨论(假设S0为完整循环节)
第一种情况:
S0S0S0(只有 完整循环节 的情况)
这里next[len]必然等于len(2*S0),非常好理解的是ans=len(S0),确实是最短循环节
第二种情况:
S0S0a(a为 不完整循环节,为S0的一部分)
next[len]=len(S0+a),len-next[len]=len(S0),仍然显而易见的是ans仍然是最短循环节(太神奇了吧)
虽然实际情况不只这两种,但大多可抽象为这两种,完整循环节或是不完整循环节(其实这两种都可以归为一类),其他的类似的种类还有:
S0a
S0S0S0a
S0S0
S0S0S0S0a
相信你已经看得出来尽管循环节的数量会有变化,但实际没有多大差别
在这里我推荐hdu 3746作为练手题
ans=len-next[len]
问题2
之后我又学习到了后缀数组,后缀数组也能够求最小循环节(不过时间复杂度比较高,一般不能用倍增,只能用DC3,虽然我还不会,但理解后缀的最小循环节求法对于后缀数组的理解,应该能够得到大幅度的加深)
思想
abababab
形如这样的字符串,他的最小循环节等于
len-h[rank[0]]
什么意思呢?
rank[0]代表字符串整体在后缀排序后所处在的位置
h[rank[0]]代表abababab与后缀排序中前一项的公共部分,那么前一项是什么呢?一定是ababab(少一个循环节的字符串),为什么?因为这种字符串的后缀无非两种:
ababab…
bababa…
在abababab前的,一定是和他大小最相近的,首先排除第二种,一位首字母大小就不相同了,然后在想,在第一种中离原字符最相近的,就是正好少了一个循环节的后缀