重复字符串的判定问题,上一篇文章给出了第一种解法: 重复字符串的判定问题(质数检验法)
该篇文章给出另一种解法,基于 kmp 算法的判定。
该算法是举例发现的,
设循环单元长度为 l, 设 len = l*n
则 [0,l) = [l, 2*l) = [2*i ,3*l ) = [3*l, 4*l) = [4*l, 5*l) = …… = [(n-1)*l, n*l)
那么,原串必然存在前后缀相等。因而可以联想到 kmp 算法的 next 数组(在作者认知,称为t1Length 数组),
给出一个观察后的结论,如果前后缀匹配的长度是不匹配长度的整数倍(含 1)则串是重复的。
构思这个解决方法时,掉过一个坑,认为只要匹配的长度大于不匹配的长度即可。举反例可以推翻这个设想:
abcabca,前后缀匹配的长度为 4,而不匹配的长度为 3,4 > 3 但是它明显不是一个重复结构。
下面证明命题:如果前后缀匹配的长度是不匹配长度的整数倍(含 1)则串是重复的
设对长为 strLen 的串计算 kmp 算法的 t1 数组的最后一个元素值 m 表示整个串前后缀匹配长度为 m,
观察整个串,若匹配的长度 m 比不匹配的长度 notC 更长,则说明它必然是一个重复的
且 m 一定是 notC 的整数倍.
这是充分必要的.
1.假设长度为 len 的串是重复的,最小单元是 notC,则 m(len-notC)
即是 t1 数组的最后一个元素值。且 m 一定是 notC 的整数倍。
2.假设 m 是串 str 的 t1 数组最后元素的值,且 m 是 notC 的整数倍,便于理解设
m=3*notC,len=4*notC,则首先有 str[0,3*notC) = str[notC,4*notC),将
str[0,3*notC) 分为三部分,依次与 str[notC,4*notC) 比较,可知
str[0,notC)=str[notC,2*notC),
str[notC,2*notC)=str[2*notC,3*notC),
str[2*notC,3*notC)=str[3*notC,4*notC)
于是有 str[0,notC)=str[notC,2*notC)=str[2*notC,3*notC)=str[3*notC,4*notC)
这也就证明了 str 是一个重复的字符串
当 m=n*notC 时,同样也可以把 str[0,n*notC) 拆为 n 部分:
str[0,notC), str[notC,2*notC)…. , str[(n-1)*notC, n*notC) 依次与
str[notc,(n+1)*notC) 的 n 部分:
str[notC,2*notC)…. , str[(n-1)*notC, n*notC)各项比较则可以得出
str[0,notC) = str[notC,2*notC) = …… = str[(n-1)*notC, n*notC) = str[notc,(n+1)*notC)
因此 str 是一个重复的字符串
原理已经非常简单,t1 数组计算的方法也十分明显。问题已经非常轻松地解决了。
代码见:https://github.com/juniorfans/repeatString