POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)
来源:互联网 发布:解决mac下迅雷慢 编辑:程序博客网 时间:2024/06/06 06:41
后缀数组模板题
照着kuangbin大神的模板敲得~~
/*
* POJ 1743 Musical Theme
* 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。
* “主题”是整个音符序列的一个子串,它需要满足如下条件:
* 1.长度至少为5个音符
* 2.在乐曲中重复出现(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值。)
* 3.重复出现的同一主题不能有公共部分。
*
* 先转化成相邻两项的差值,然后就是找不可重叠重复子串。
* 做法就是二分答案LEN
* 然后根据height值进行分组
*/
分析:
#include<cstdio>#include<algorithm>using namespace std;#define rep(i,s,t) for(int i=(s);i<(t);i++)#define per(i,t,s) for(int i=(t);i>=(s);i--)const int INF = 1e9 + 9;const int N = 20000 + 9;/********************倍增算法*后缀数组模板*******************************//**suffix array*倍增算法 O(n*logn)*待排序数组长度为n,放在0~n-1中,在最后面补一个0*build_sa( ,n+1, );//注意是n+1;*getHeight(,n);*例如:*n = 8;*num[] = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0,其他大于0*rank[] = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值,rank[n]必定为0无效值*sa[] = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值,sa[0]必定为n是无效值*height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值**/int sa[N], t1[N], t2[N], c[N], rk[N], height[N];void build_sa (int s[], int n, int m) { int i, k, p, *x = t1, *y = t2; for (i = 0; i < m; i++) c[i] = 0; for (i = 0; i < n; i++) c[x[i] = s[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 (k = 1; k <= n; k <<= 1) { p = 0; for (i = n - k; i < n; i++) y[p++] = i; for (i = 0; i < n; i++) if (sa[i] >= k) y[p++] = sa[i] - k; 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]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + k] == y[sa[i] + k] ? p - 1 : p ++; if (p >= n) break; m = p; }}void getHeight (int s[], int n) { int i, j, k = 0; for (i = 0; i <= n; i++) rk[sa[i]] = i; for (i = 0; i < n; i++) { if (k) k--; j = sa[rk[i] - 1]; while (s[i + k] == s[j + k]) k++; height[rk[i]] = k; }}/********************************************************************************/int s[N];bool ok (int n, int k) { int Max = sa[1], Min = sa[1]; for (int i = 2; i <= n; i++) { if (height[i] < k) Max = Min = sa[i]; else { if (sa[i] < Min) Min = sa[i]; if (sa[i] > Max) Max = sa[i]; if (Max - Min > k) return 1; } } return 0;}int main() { //freopen ("f.txt", "r", stdin); int n; while (~scanf ("%d", &n) && n) { rep (i, 0, n) scanf ("%d", &s[i]); per (i, n - 1, 1) s[i] = s[i] - s[i - 1] + 90; // rep(i,0,n)printf("%d ",s[i]);printf("\n"); n--; rep (i, 0, n) s[i] = s[i + 1]; s[n] = 0; // rep(i,0,n)printf("%d ",s[i]);printf("\n"); build_sa (s, n + 1, 200); getHeight (s, n); int l = 1, r = n / 2; while (l < r) { int mid = l + (r - l + 1) / 2; if (ok (n, mid) ) l = mid; else r = mid - 1; } if (l < 4) puts ("0"); else printf ("%d\n", l + 1); } return 0;}
0 0
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)
- POJ 1743 Musical Theme(后缀数组求不可重叠最长重复子串)
- POJ 1743 Musical Theme (后缀数组加二分求不可重叠最长重复子串)
- POJ 题目1743 Musical Theme(后缀数组,求一个串中最长不重叠重复子串)
- POJ - 1743 Musical Theme (后缀数组求不可重叠最长重复子串)
- poj 1743 Musical Theme(最长不重叠重复子串 后缀数组+二分)
- POJ-1743 Musical Theme (后缀数组 不重叠最长重复子串)
- poj 1743 Musical Theme 【后缀数组 最长不重叠重复子串】
- POJ - 1743 - Musical Theme(后缀数组 - 不可重叠最长重复子串)
- POJ 1743 Musical Theme(不可重叠最长重复子串 后缀数组)
- POJ 1743 Musical Theme(后缀数组 求最长不重复子串)
- POJ 173 Musical Theme 后缀数组 + 最长不重叠重复子串
- Poj 1743 Musical Theme (后缀数组 不可重叠最长重复子串)
- poj 1743 Musical Theme (后缀数组 不可重叠最长重复子串)
- poj 1743 Musical Theme(不可重叠的最长重复子串,后缀数组)
- POJ 1743 Musical Theme ( 后缀数组 + 二分 不可重叠最长重复子串 )
- POJ 1743 Musical Theme 后缀数组 不可重叠最长重复子串
- C/C++程序编译过程
- Lock与synchronized 的区别
- mssql动态sql查询使用in
- TCP UDP IP 协议汇总(未完待续)
- postgresql 安装教程
- POJ 1743 Musical Theme (后缀数组,求最长不重叠重复子串)
- java面试题
- 分布式锁的实现方式
- 344. Reverse String--leetcode
- 修改host访问外网(科普文无恶意)
- 剑指Offer_61_序列化二叉树
- SwipeRefreshLayout进入界面自动刷新效果
- jQuery学习心得----第三集:jQuery中的DOM操作总结
- android自定义view