一、相关定义及原理
以下描述中,s表示字符串,n为字符串s的长度:
s[i]
或
s
i
s_i
si表示字符串的第i个字符,从0开始。
使用python切片写法表示字符串的子串
s[x:y]
表示字符串s下标范围为左闭右开区间[x, y)中的字符
s[:y]
等价于s[0:y]
s[x:]
等价于s[x:n]
- 循环节:若某个字符串是由某个子串循环多次构成的,那么就称该子串为原串的循环节。(本文中循环节循环次数满足大于1次)
假设字符串s有长度为T的循环节,那么一定有: s i = s i + k T s_i=s_{i+kT} si=si+kT,k是整数。 - 完全循环节:字符串由若干完整的循环节构成,这样的循环节叫完全循环节。
如果完全循环节的长度为T,那么有n%T == 0
- 不完全循环节:字符串由若干完整的循环节和循环节的真前缀构成。
如果不完全循环节的长度为T,那么有n%T != 0
- 有长为n的字符串s,s的最短循环节为
n-next[n]
(s的前缀表为next
,next[i]
表示s的长为i的前缀s[:i]
的最长相等前后缀的长度。可以使用KMP算法求出。)
二、证明
证明引理
引理1:字符串的循环节的长度都是最短循环节长度的倍数
最短循环节长度记为T
反证法:
假设存在循环节长度为U,满足
U
>
T
U>T
U>T,且U不是T的倍数。
由于最短循环节长度为T,则
s
i
=
s
i
+
a
T
s_i=s_{i+aT}
si=si+aT,其中a为整数。
由于存在循环节长度为U,则
s
i
=
s
i
+
b
U
s_i=s_{i+bU}
si=si+bU,其中b为整数。
因此存在
s
i
=
s
i
+
a
T
+
b
U
s_i = s_{i+aT+bU}
si=si+aT+bU,其中a、b为整数。
因为U不是T的倍数,因此可以写为
U
=
k
T
+
r
U = kT+r
U=kT+r,
r
r
r为
U
U
U mod
T
T
T且
r
>
0
r>0
r>0
即
U
>
k
T
U>kT
U>kT且
U
<
(
k
+
1
)
T
U<(k+1)T
U<(k+1)T,亦即
U
+
T
>
(
k
+
1
)
T
U+T>(k+1)T
U+T>(k+1)T
因此有
0
<
(
k
+
1
)
T
−
U
<
T
0 < (k+1)T-U < T
0<(k+1)T−U<T
使a=k+1,b=-1,那么
s
i
=
s
i
+
(
k
+
1
)
T
−
U
s_i=s_{i+(k+1)T-U}
si=si+(k+1)T−U,所以存在长为(k+1)T-U的循环节。
已知T是最短循环节,而现在存在更短的长位(k+1)T-U的循环节,存在矛盾,假设不成立,原命题得证。
证明:如果一个字符串的最小循环节是不完全循环节,那么该字符串没有完全循环节
记字符串最小循环节长度为T,那么有n%T != 0
根据引理1,字符串的其他循环节长度都是最小循环节长度的倍数,为kT。k是正整数。n%(k*T)
也一定不为0。
因此该字符串没有完全循环节。