【后缀数组】 POJ 1743 Musical Theme
2014-07-10 21:28
337 查看
后缀数组+二分,和上一题类似,比较简单。
#include <iostream> #include <sstream> #include <algorithm> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <bitset> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <climits> #define maxn 20005 #define eps 1e-6 #define mod 10007 #define INF 99999999 #define lowbit(x) (x&(-x)) //#define lson o<<1, L, mid //#define rson o<<1 | 1, mid+1, R typedef long long LL; using namespace std; int s[maxn]; int t[maxn], t2[maxn], c[maxn], sa[maxn]; void build(int n, int m) { int i, k, p, *x = t, *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]] == y[sa[i-1]] && y[sa[i]+k] == y[sa[i-1]+k] ? p-1 : p++; if(p >= n) break; m = p; } } int rank[maxn], height[maxn]; void getheight(int n) { int i, j, k = 0; for(i = 0; i <= n; i++) rank[sa[i]] = i; for(i = 0; i < n; i++) { if(k) k--; j = sa[rank[i]-1]; while(s[i+k] == s[j+k]) k++; height[rank[i]] = k; } } bool is(int p, int n) { int i, _max = 0, _min = INF; for(i = 1; i <= n; i++) { if(height[i] >= p) { _max = max(_max, sa[i]); _min = min(_min, sa[i]); _max = max(_max, sa[i-1]); _min = min(_min, sa[i-1]); } else { if(_max - _min > p) return true; _max = 0; _min = INF; } } if(_max - _min > p) return true; else return false; } int search(int n) { int bot = 0, top = 10000, mid, res = 0; while(top >= bot) { mid= (top+bot)>>1; if(is(mid, n)) bot = mid+1, res = max(res, mid); else top = mid-1; } return res; } int main(void) { int i, n, ans; while(scanf("%d", &n), n!=0) { for(i = 0; i < n; i++) scanf("%d", &s[i]); for(i = 0; i < n-1; i++) s[i] = s[i+1] - s[i]+100; s[i] = 0; build(n, 200); getheight(n-1); ans = search(n-1); if(ans >= 4) printf("%d\n", ans+1); else printf("0\n"); } return 0; }
相关文章推荐
- Poj 1743 Musical Theme (后缀数组 不可重叠最长重复子串)
- 【POJ】1743 Musical Theme 【后缀数组】
- 【后缀数组】[POJ 1743]Musical Theme
- 【后缀数组】【二分答案】【差分】poj1743 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 后缀数组 楼教主男人八题之一
- 【后缀数组】[POJ1743]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 后缀数组模板+用后缀数组求不覆盖最长重复子序列