【Luogu P2852】[USACO06DEC]Milk Patterns G

链接:

洛谷

题目大意:

给出一个数字串找到一个最大的子串使得其出现次数大于等于 k

思路:

简单题。对后缀排序后,求 height 数组。那么任意一段区间 [l,r] 后缀的 height 的最小值就是它们的 LCP,也是出现次数为 rl+1 的最大子串。那么枚举左端点,长度为 k,加 ST 表即可。

代码:

const int N = 2e4 + 10, M = 1e6 + 10;
inline ll Read() {
ll x = 0, f = 1;
char c = getchar();
while (c != '-' && (c < '0' || c > '9')) c = getchar();
if (c == '-') f = -f, c = getchar();
while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
return x * f;
}
int n, m, k;
int s[N], c[M];
int x[N], y[N], sa[N], height[N], Rank[N];
void SA() {
for (int i = 1; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n; i++) c[x[i] = s[i]]++;
for (int i = 2; i <= m; i++) c[i] += c[i - 1];
for (int i = n; i; i--) sa[c[x[i]]--] = i;
for (int k = 1; k <= n; k <<= 1) {
int num = 0;
for (int i = n - k + 1; i <= n; i++) y[++num] = i;
for (int i = 1; i <= n; i++)
if (sa[i] > k) y[++num] = sa[i] - k;
for (int i = 1; i <= m; i++) c[i] = 0;
for (int i = 1; i <= n; i++) c[x[i]]++;
for (int i = 2; i <= m; i++) c[i] += c[i - 1];
for (int i = n; i; i--) sa[c[x[y[i]]]--] = y[i], y[i] = 0;
swap(x, y);
x[sa[1]] = 1, num = 1;
for (int i = 2; i <= n; i++)
x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]? num: ++num);
m = num;
if (n == m) break;
}
return ;
}
void Height() {
for (int i = 1; i <= n; i++) Rank[sa[i]] = i;
int h = 0, j;
for (int i = 1; i <= n; height[Rank[i++]] = h)
for (h? h--: 0, j = sa[Rank[i] - 1]; s[i + h] == s[j + h]; h++);
return;
}
int f[N][25], ans;
int QueryMin(int l, int r) {
int t = log2(r - l + 1);
return min(f[l][t], f[r - (1 << t) + 1][t]);
}
int main() {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
n = Read(), k = Read() - 1;
for (int i = 1; i <= n; i++) s[i] = Read(), m = max(m, s[i]);
SA();
Height();
memset (f, 127 / 3, sizeof f);
for (int i = 1; i <= n; i++) f[i][0] = height[i];
for (int j = 1; j <= 23; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = min(f[i][j - 1], f[i + (1 << j - 1)][j - 1]);
}
for (int i = 1; i <= n - k + 1; i++)
ans = max(QueryMin(i, i + k - 1), ans);
printf ("%d\n", ans);
return 0;
}
posted @   Jayun  阅读(36)  评论(0编辑  收藏  举报
编辑推荐:
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
阅读排行:
· [翻译] 为什么 Tracebit 用 C# 开发
· 腾讯ima接入deepseek-r1,借用别人脑子用用成真了~
· Deepseek官网太卡,教你白嫖阿里云的Deepseek-R1满血版
· DeepSeek崛起:程序员“饭碗”被抢,还是职业进化新起点?
· 深度对比:PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
历史上的今天:
2020-12-09 【YBTOJ】求 f 函数
2020-12-09 【YBTOJ】划分数列
点击右上角即可分享
微信分享提示