此题想了我好久啊。。硬是没相通如果左边怎么匹配。paper上只说了匹配右边
假设一个长度为l的子串重复出现两次,那么它必然会包含s[0]、s[l]、s[l*2]...之中的相邻的两个。不难看出,该重复子串必然会包含s[0..l]或s[l..l*2]或s[l*2..l*3]...。所以,我们可以枚举一个i,对于每个i*l的位置,利用后缀数组可以求出s[i*l..(i+1)*l]向后延伸的长度k。k/l+1即i*l..(i+1)*l这一段重复出现的次数。但还有一种情况。考虑以下的字符串:
aababababab
如果长度下还有多余的那么我要不全一个长度l,那么我就向左移(l-k%l)个单位 即:i-(l-k%l) 那么在判断左边是否有可以匹配的
假设现在l=2,i=1。则当前得到的子串为ba.用后缀数组可以求得k=7,则ba共重复出现了4次。但实际上,长度为2的子串重复出现最多的应该是“ab”,出现了5次。可以看出来,上述方法求得的k不能整除l,故可能在i的左边位置存在一个子串能完整重复覆盖i这个子串后面的子串。这里是i左边一位的“ab”子串。分析下这种情况,可以得知,如果以i-(l-k%l)开头的长度为l的子串,向后延伸的长度能大于k的话,那么有一个子串出现次数为k/l+2。
就这样,问题得到解决。
我用倍增法 2660ms
我用dc3 2540ms
对于前面那题dc3就显示出强烈的优势,在这优势不大
但是我看spoj此题有非常快的方法貌似下于1s 求大神给出此种解法