题目内容
题目描述
给你一个字符串 ,它是由某个字符串 不断自我连接形成的(保证至少重复 次)。但是字符串 是不确定的,现在只想知道它的最短长度是多少。
输入格式
第一行一个整数 ,表示给出字符串的长度。
第二行给出字符串 的一个子串,全由小写字母组成。
输出格式
仅一行,表示 的最短长度。
输入输出样例 #1
输入 #1
1 | 8 |
输出 #1
1 | 3 |
说明/提示
样例输入输出 1 解释
对于样例,我们可以利用 不断自我连接得到 ,读入的 ,是它的子串。
规模与约定
对于全部的测试点,保证 。
思路讲解
给出子串,找出最短循环节。
最大公共前后缀。
结论就是N-pi[N]。其实我也不是很懂。
不能够使用二分,因为周期并没有单调性。
这道题目 hash 怎么做?
哈希做法思路
核心观察:字符串 的最小周期为 ,当且仅当 是满足以下条件的最小正整数:
这等价于: 去掉前 个字符得到的后缀,与去掉后 个字符得到的前缀完全相同。即:
用多项式哈希预处理后,每次子串比较 。从 开始枚举,第一个满足条件的 就是答案。总复杂度 。
参考代码:
1 |
|
用了双哈希避免冲突。本质上和 KMP 中 的经典做法等价,只是换了一种判断周期的手段。
详细解释关键观察
这其实就是把逐字符的条件"打包"成了一个子串相等的条件,是同一件事的两种说法。
逐字符展开:两个长度相同的子串相等,就是对应位置的字符全部相等。把两个子串的对应位置写出来:
| 前缀中的第 个字符 | 后缀中的第 个字符 |
|---|---|
| 前缀的第 个字符是 ,后缀的第 个字符是 。 | |
| 所以"两个子串相等" 每一行都对应相等 对所有 成立。 | |
用例子直观感受:取 cabcabca,: |
1 | 前缀(去掉后3个):c a b c a |
每个字符都和它后面第 个字符相同,这就是"周期为 "的含义。把这些逐个比较合在一起看,就是前缀和后缀相等。
两种说法完全等价,只是视角不同:一个是逐字符看,一个是整体看。

把这个列出来以后,我们就知道了周期 p 的成立条件是什么。可以通过枚举 p,非常简单的使用字符串哈希检验答案。
AC代码
https://www.luogu.com.cn/record/221541535
源代码
1 | // Problem: P4391 [BalticOI 2009] Radio Transmission 无线传输 |