一个字符串奇妙的问题,引发了一系列的思考。在此记录一下。
猜想:
定义向右旋转的概念:[abcdef] 向右旋转一下得到 [fabcde],即转出右边界的字符依次添加到左边界。
定理:字符串s[1~n]循环向右旋转k次和s原来的字符串相等,那么
1)当n%k == 0 时,该字符串由s的前k个字符循环重复组成
2)当n%k ≠ 0时,该字符串由s的更小的前m个字符循环重复组成 (1≤m<k)
下面着重考虑2)
设s循环后的字符串是s',
当 n%k ≠ 0时,设p=n%k,(0<p<k), s[1~n] == 整数倍个s[1~k] + s[1~p],问题转化为如果我们能够用s[1~p]构造出s[1~k],那么我们一定可以用s[1~p]构造出s[1~n].
记s' = s[1~k]
此时由我们将原问题s字符串向右旋转k位后得到的字符串和原来的字符串相同 转化成 s'向右旋转p位得到的字符串和原来的字符串相同的问题。问题本质是一样的,只是规模减小了。如果我们能够再次尝试用s'[1~p]构造出s'[1~k] :
1)如果能够构造出,那么显然s'[1~p]就是我们寻找的循环构造源字符串的子串
2)如果不能那么我们可以进一步把问题继续转化成规模更小的子问题并且重复以上的尝试操作,因为p随着问题规模不断减小,当p减小为1的时候,必定能整除任何整数。所以这样的构造子串必定存在。
那么设s的前p个的字符为s[1~p],
着重观察,s的前k个字符串和s的后p个字符串,因为s'[1~k]是由s[p+1 ~ k]s[1 ~ p]组成的
所以有:
s[1~k] == s'[1~k] == s[p+1 ~ k]s[1 ~ p] == s[1~k-p]s[1~p] == s[1~p][p+1~k]
注意以上表明 s[1~k]
s[1~p][p+1~k]
s[p+1~k]s[1~p]
和 s[1~k-p]s[1~p] 完全相同
下面我们探讨以s[1~p]作为循环因子,来循环构造s[1~k],如果k%p==0,那么s[k]可以由s[p]循环构造而成; 如果k%p≠0,那么设 r=k%p,此时 k=mp+r,(m是正整数,0<r<p),此时
s[1~k] == m个s[1~p] + s[1~r] ,接下来如果我们可以用 s[1~r]来构造出s[1~p],那么s[1~r]一定可以构造出s[1~k]从而也就一定可以构造出s[1~n]
此时s[1~p] == s[r+1,p]s[1~r] == s[1~p-r]s[1~r] == s[1~r]s[r+1~p].
... ...
循环因子的长度k<p<r< ....,严格单调递减,因此必存在x≥1,s由s[1~x]循环构造而成。因为当x减小到1时它必能被大于它的正整数整除,此时也就找到了循环构造因子。
n = 正整数*k +p —>尝试用p来循环表示k,若可以那么p就是循环因子,否则k%p寻找更小的循环因子
k = 正整数*p + r
p = 正整数*r + r1
r = 正整数*r1 + r2
... ...
( n=整数数*k+p < ==> n%k = p ) 称k是 p对应的除数,
同理,p是r对应的除数,
r是r1对应的除数
r1是r2对应的除数
... ...
可见余数就是不断尝试的最小循环因子的长度,余数严格单调递减到0,因此存在x ,x≥1,它对应的余数是0。
因此我们一定可以用s[1~x]构造出它对应的除数,从而依次构造出它除数对应的除数,一直构造出到k
也构造出s[1~n]
应用:
已知字符串s是由x循环构造而成的,并且x是s的最小的循环构造字串 。 证明:
在s字符串中,和s字符串最后一个字符有着最大的公共前缀字符就是前n-1个x字符串的最后一个字符
反证法:
设原始字符串s是由n个x字符串循环构造而成的,假设 n-1个x字符串构成了s字符串的前缀,并且还存在可以向左向右扩的k字符串,即(n-1)*x +k 也是s的最大公共前缀,显然x的前(x.len-k.len)个字符等于x的后(x.len-k.len)个字符,此时必有
记s原本的字符串是A,显然A字符串向右旋转x.len-k.len个字符之后,得到了字符串B,并且 A==B 。
那么由上面的定理,必存在字符串y (1≤y.len≤(x.len - k.len)),使得y = s[1~y.len] 是s的循环因子,这与x是s最小的循环因子相矛盾,所以不存在这样的k字符串。
证毕。
注意:y.len表示字符串y的长度