时间限制:
5000ms
单点时限:
1000ms
内存限制:
256MB
-
8 2 1 2 3 2 3 2 3 1
样例输出
-
4
-
解题思路:首先我们二分答案,然后用后缀数组判断每个值是否合法,在height数组上从上往下扫就行。
-
-
#include <bits/stdc++.h> using namespace std; const int maxn = 20000 + 10; int n, kk, m; int a[maxn];//原数组 int rrank[maxn];//第一关键字 int Rank[maxn];//第i个前缀排第几 int tp[maxn];//第二关键字,序号为第二关键字的排名,值为对应的第一关键字的位置 int c[maxn];//用于基数排序用的数组 int Sa[maxn];//后缀数组,排名为i的后缀是哪一个后缀 int Height[maxn];//排名为i的后缀与排名为i - 1的后缀的lcp bool judge(int *x, int loc, int ww) { if(x[Sa[loc]] == x[Sa[loc - 1]] && x[Sa[loc] + ww] == x[Sa[loc - 1] + ww]) return true; else return false; } void suffix() { for(int i = 1; i <= n; i++) rrank[i] = a[i]; for(int i = 1; i <= n; i++) tp[i] = i; for(int i = 0; i <= 100; i++) c[i] = 0; for(int i = 1; i <= n; i++) c[rrank[tp[i]]]++; for(int i = 1; i <= 100; i++) c[i] += c[i - 1]; for(int i = n; i >= 1; i--) Sa[c[rrank[tp[i]]]--] = tp[i]; m = 100; for(int w = 1, p = 0; w <= n; w += w, m = p) { p = 0; for(int i = n - w + 1; i <= n; i++) tp[++p] = i; for(int i = 1; i <= n; i++) { if(Sa[i] > w) tp[++p] = Sa[i] - w; } for(int i = 0; i <= m; i++) c[i] = 0; for(int i = 1; i <= n; i++) c[rrank[tp[i]]]++; for(int i = 1; i <= m; i++) c[i] += c[i - 1]; for(int i = n; i >= 1; i--) Sa[c[rrank[tp[i]]]--] = tp[i]; for(int i = 1; i <= n; i++) tp[i] = rrank[i];//重新计算rank的值 rrank[Sa[1]] = 1; p = 1; for(int i = 2; i <= n; i++) { if(judge(tp, i, w)) rrank[Sa[i]] = p; else rrank[Sa[i]] = ++p; } } for(int i = 1; i <= n; i++) { Rank[Sa[i]] = i; } int k = 0; Height[1] = 0; for(int i = 1; i <= n; i++) { if(k) k--; while(a[i + k] == a[Sa[Rank[i] - 1] + k]) { k++; } Height[Rank[i]] = k; } } bool ok(int mid) { int sum = 1; for(int i = 2; i <= n; i++) { if(Height[i] >= mid) { sum++; } else { if(sum >= kk) return true; sum = 1; } } return false; } int main() { scanf("%d%d", &n, &kk); for(int i = 1; i <= n; i++) { scanf("%d", &a[i]); } suffix(); int l = 0; int r = n; int re = l; while(l <= r) { int mid = (l + r)>>1; if(ok(mid)) { l = mid + 1; re = mid; } else r = mid - 1; } printf("%d\n", re); return 0; }
描述
小Hi平时的一大兴趣爱好就是演奏钢琴。我们知道一个音乐旋律被表示为长度为 N 的数构成的数列。
小Hi在练习过很多曲子以后发现很多作品自身包含一样的旋律。旋律是一段连续的数列,相似的旋律在原数列可重叠。比如在1 2 3 2 3 2 1 中 2 3 2 出现了两次。
小Hi想知道一段旋律中出现次数至少为K次的旋律最长是多少?
输入
第一行两个整数 N和K。1≤N≤20000 1≤K≤N
接下来有 N 个整数,表示每个音的数字。1≤数字≤100
输出
一行一个整数,表示答案。