hihoCoder 1403 后缀数组一·重复旋律(最长可重叠重复子串问题)
2017-07-17 19:17
441 查看
描述
小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
输出
一行一个整数,表示答案。样例输入
8 2 1 2 3 2 3 2 3 1
样例输出
4
思路:
两个排名不相邻的最长公共前缀定义为排名在它们之间的Height的最小值。
二分答案,把height划分集合,height<mid就重新划分,这样保证了每个集合中的LCP>=mid,如果有一个集合数量>=k那么mid就符合。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 1e5+5; int t1[maxn], t2[maxn], c[maxn]; int ra[maxn], height[maxn]; int sa[maxn], num[maxn]; bool cmp(int *r, int a, int b, int l) { return r[a]==r[b]&&r[a+l]==r[b+l]; } void da(int str[], int sa[], int ra[], int height[], int n, int m) { n++; int i, j, p, *x = t1, *y = t2; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[i]=str[i]]++; for(i = 1; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; for(j = 1; j <= n; j<<=1) { p = 0; for(i = n-j; i < n; i++) y[p++] = i; for(i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i]-j; for(i = 0; i < m; i++) c[i] = 0; for(i = 0; i < n; i++) c[x[y[i]]]++; for(i = 1; i < m; i++) c[i] += c[i-1]; for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i-1], sa[i], j) ? p-1 : p++; if(p >= n) break; m = p; } int k = 0; n--; for(i = 0; i <= n; i++) ra[sa[i]] = i; for(i = 0; i < n; i++) { if(k) k--; j = sa[ra[i]-1]; while(str[i+k]==str[j+k]) k++; height[ra[i]] = k; } } int n, k; bool judge(int x) { int tmp = 1; for(int i = 1; i < n; ) { int cnt = 1; int j = i+1; while(height[j] >= x && j <= n) j++, cnt++; tmp = max(tmp, cnt); i = j; } return tmp >= k; } int main(void) { while(cin >> n >> k) { for(int i = 0; i < n; i++) scanf("%d", &num[i]); da(num, sa, ra, height, n, 127); int l = 0, r = n, ans = 0; while(l <= r) { int mid = (l+r)/2; if(judge(mid)) ans = mid, l = mid+1; else r = mid-1; } printf("%d\n", ans); } return 0; }
相关文章推荐
- hihoCoder 1407 后缀数组二·重复旋律2 && POJ 1743 Musical Theme(最长不可重叠重复子串问题)
- Hiho 121 后缀数组二·重复旋律2(最长不可重叠重复子串问题)
- HihoCoder - 1403 最长可重叠子串问题 二分+暴力
- 重复旋律 后缀数组 板子 最长可重叠重复子串问题
- 后缀数组经典题---不可重叠最长重复子串 poj1743
- POJ 1743 (后缀数组+不重叠最长重复子串)
- 最长重复子串(可重叠) 后缀数组
- 后缀数组(可重叠的k次最长重复子串)
- 【HIHOCODER 1403】后缀数组一·重复旋律(后缀数组)
- 后缀数组(至少重复k次的可重叠的最长重复子串)—— POJ 3882
- POJ-1743 Musical Theme 字符串问题 不重叠最长重复子串
- 后缀数组--(可重叠最长重复子串问题)
- hihoCoder 1415 后缀数组三·重复旋律3(最长公共子串)
- 后缀数组 最长不可重叠重复子串问题
- poj3261Milk Patterns(后缀数组+可重叠的 k 次最长重复子串)
- 最长重复不重叠子串 poj 1743
- poj 3261 Milk Patterns 最长的出现最少k次的重复(可重叠)子串 后缀数组
- hihoCoder 1403 后缀数组 重复旋律
- POJ - 3261 - Milk Patterns(后缀数组-可重叠最长重复子串)
- Poj 1743 Musical Theme (后缀数组 不可重叠最长重复子串)