1. 题目解析与算法选择
1.1 题目核心需求
这道题目要求我们在一个长度为N的整数序列中,找到至少重复K次的最长子序列长度。这里的"重复"允许子序列重叠出现,比如在序列1 2 3 2 3 2 3 1中,2 3 2 3可以看作重复了两次(分别在位置2-5和4-7)。
关键点在于:
- 子序列必须是连续的
- 允许重叠出现
- 需要找到最长的满足条件的子序列
1.2 算法选择思路
对于这类子串匹配问题,常见的解法有:
- 暴力枚举:检查所有可能的子串,时间复杂度O(n³)
- 后缀数组:可以优化到O(nlogn)
- 哈希+二分:时间复杂度O(nlogn)
考虑到题目中N的范围是2×10⁴,纯暴力解法显然不可行。这里我们选择哈希+枚举的方法,通过预处理字符串哈希来快速比较子串是否相同,将时间复杂度优化到O(n²),在题目给定的数据范围内是可以接受的。
提示:在实际比赛中,如果N更大(比如1e5以上),就需要考虑更高效的算法如后缀数组了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 哈希算法原理与实现
2.1 字符串哈希基础
字符串哈希是将字符串映射为一个数字的技术,常用的哈希方法是将字符串看作一个base进制的数。对于字符串s,其哈希值为:
code复制hash(s) = s[0]×base^(n-1) + s[1]×base^(n-2) + ... + s[n-1]×base^0
这种哈希方法的一个重要性质是:我们可以用前缀哈希数组在O(1)时间内计算任意子串的哈希值。
2.2 哈希预处理实现
在代码中,我们做了两个预处理:
cpp复制mul[0]=1;
for(int i=1;i<=n;i++){
mul[i]=mul[i-1]*19260817;//预处理base的幂次
}
for(int i=1;i<=n;i++){
hs[i]=hs[i-1]*19260817+a[i];//计算前缀哈希
}
这里:
mul[i]存储的是base^i(base=19260817)hs[i]存储的是前i个元素的前缀哈希值
2.3 子串哈希计算
要计算子串a[l..r]的哈希值,公式为:
code复制hash(l,r) = hs[r] - hs[l-1] * mul[r-
