字符串哈希 - # [USACO06DEC] Milk Patterns G

题目描述

农夫约翰注意到他的奶牛所产的牛奶质量每天都在变化。经过进一步调查,他发现虽然无法预测牛奶质量从一天到下一天的变化,但每天的牛奶质量中存在一些规律模式。

为了进行严格的研究,他发明了一种复杂的分类方案,其中每个牛奶样本被记录为一个介于 \(0\)\(1,000,000\) 之间的整数,并记录了一头奶牛在 \(N\ (1 \le N \le 20,000)\) 天内的数据。他希望找到一个最长的样本模式,该模式至少重复 \(K\ (2 \le K \le N)\) 次。这可能包括重叠的模式——例如,1 2 3 2 3 2 3 1 中的 2 3 2 3 重复了两次。

帮助农夫约翰找到样本序列中最长的重复子串。保证至少有一个子串重复至少 \(K\) 次。

输入格式

\(1\) 行:两个用空格分隔的整数:\(N\)\(K\)

\(2\) 行到第 \(N+1\) 行:\(N\) 个整数,每行一个,第 \(i\) 行表示第 \(i\) 天的牛奶质量。

输出格式

\(1\) 行:一个整数,表示至少出现 \(K\) 次的最长子串的长度。

输入输出样例 #1

输入 #1

8 2
1
2
3
2
3
2
3
1

输出 #1

4

题解

  • 思考1: 问题求 至少出现 \(k\) 次的最长子串s 。
  • 思考2: 答案具有单调性,长度 \(L\) 的子串满足至少出现 \(k\) 次,长度为 \(1-L-1\) , 必然满足出现 \(k\) 次。
  • 思考3: 构造函数 \(F[x] \le k\) ,为可行解。 \(F[x]\) 是否存在一个子串长度为 \(x\) ,满足出现次数为 \(k\) 次。
  • 思考4: 统计长度为 \(x\) 的字符串的 \(hash\) 值,重复次数超过 \(k\) 次,即为可行解。枚举起点 \(i\) ,利用 GetHash函数。
#include <bits/stdc++.h>
#define ULL unsigned long long
using namespace std;
const int N = 2e4 + 10;
const int base = 131;
const ULL mod1 = 1000000007, mod2 = 1000000009;
int n, k, a[N];
ULL pow1[N], pow2[N];
ULL pre1[N], pre2[N];

void init() {
    pow1[0] = pow2[0] = 1;
    for (int i = 1; i <= n; i++) {
        pow1[i] = pow1[i-1] * base % mod1;
        pow2[i] = pow2[i-1] * base % mod2;
    }
    for (int i = 1; i <= n; i++) {
        pre1[i] = (pre1[i-1] * base + a[i]) % mod1;
        pre2[i] = (pre2[i-1] * base + a[i]) % mod2;
    }
}

ULL get_hash(int l, int r) {
    ULL  h1 = (pre1[r] - pre1[l-1] * pow1[r-l+1] % mod1 + mod1) % mod1;
    ULL  h2 = (pre2[r] - pre2[l-1] * pow2[r-l+1] % mod2 + mod2) % mod2;
    return h1 * mod1 + h2;
}

bool check(int len) {
    map<ULL,int> mp;
    for (int i = 1; i + len - 1 <= n; i++) {
        ULL h = get_hash(i, i + len - 1);
        mp[h]++;
        if (mp[h] >= k) return 1;
    }
    return 0;
}

int main() {
    scanf("%d%d", &n, &k);
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    init();
    int l = 1, r = n;
    while (l < r) {
        int mid = (l + r + 1) >> 1;
        if (check(mid)) l = mid; else r = mid - 1;
    }
    printf("%d\n", l);
    return 0;
}
posted @ 2026-06-11 15:50  alice_ss  阅读(5)  评论(0)    收藏  举报
//雪花飘落效果