1 条题解
-
0
题目重述 给定一个字符串 ,判断是否存在一个字符串 和一个正整数 (),使得 由两个 重叠 个字符拼接而成,即 其中 表示 去掉前 个字符的后缀。 例如,, 时,。
要求:若存在,输出任意一个可能的 ;否则输出 "NO"。 数据范围:。
数学建模 设 ,。由拼接方式知: 因此重叠长度 。
题目要求 ,即 解不等式:
左边
右边
由于 是整数,所以 的取值范围为:
换言之,我们只需枚举 在这个区间内的每个整数,令 ,然后验证以下两个条件:
后缀条件: 等于 (因为 的后半部分应该是 ,而 恰好是 的 段)
前缀条件: 等于 (因为 的前 个字符与后 个字符相同——它们就是重叠部分)
若存在某个 同时满足这两个条件,则 即为答案。
关键观察 如果直接对每个 比较子串,最坏情况需要 ,不可接受。
我们需要一种能在 时间内判断任意两个子串是否相等的方法。
常用的工具有:字符串哈希、Z 函数、前缀函数(KMP)。这里选用简单高效的哈希法。
算法设计(哈希法)
- 预处理哈希 选择一个大质数模数 (例如 )或使用自然溢出()。定义基数 (例如 或 )。 对于字符串 (下标从 开始),计算前缀哈希数组 和幂数组 :
则子串 ()的哈希值为:
若使用自然溢出(unsigned long long),则自动模 ,无需取模操作。
- 枚举 从 到 ,依次检查:
计算 (此时 自动成立)
检查 $\text{hash}(m, n-1) \stackrel{?}{=} \text{hash}(L, m-1)$
检查 $\text{hash}(0, L-1) \stackrel{?}{=} \text{hash}(m-L, m-1)$
如果两个条件都满足,则输出 ,结束程序。
若循环结束未找到,输出 "NO"。
边界情况处理 当 时, 的取值范围为空(因为 ),直接输出 "NO"。例如 或 不可能构成错误。
注意题目明确:完全重叠()或简单拼接()不算错误,我们的枚举范围自然排除了这些情况。
字符串中可能包含相同字符,哈希能够正确处理。
复杂度分析 预处理哈希:
枚举 :最多 次
每次判断:
总时间复杂度:
空间复杂度:(存储哈希数组和幂数组)
对于 ,完全可行。 必要性: 若存在 和 使得 ,设 ,则 ,故 。由 可得 在 到 之间。
因为 ,所以条件1成立。
又因为 的前 个字符与后 个字符相同(即重叠部分),所以 ,条件2成立。 因此算法一定会找到这样的 。
充分性: 若对于某个 满足上述两个条件,令 ,。条件1说明 ,条件2说明 。那么 ,且 满足 (由 的范围保证),因此 是一个合法解。
综上,算法正确。
- 1
信息
- ID
- 6615
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 3
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者