后缀数组【倍增计数排序求sa】poj1743
2017-04-01 20:50
309 查看
#include <cstdio> #include <cmath> #include <cstdlib> #include <algorithm> #define maxn 25001 using namespace std; int wa[maxn], wb[maxn], wv[maxn], ws[maxn]; int cmp(int *r, int a, int b, int l) {return r[a] == r[b] && r[a + l] == r[b + l];} void da(int *r, int *sa, int n, int m) { int i, j, p, *x = wa, *y = wb, *t; for (i = 0; i < m; i++) ws[i] = 0; for (i = 0; i < n; i++) ws[x[i] = r[i]]++; for (i = 1; i < m; i++) ws[i] += ws[i - 1]; for (i = n - 1; i >= 0; i--) sa[--ws[x[i]]] = i; for (j = 1, p = 1; p < n; j *= 2, m = p) { for (p = 0, 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 < n; i++) wv[i] = x[y[i]]; for (i = 0; i < m; i++) ws[i] = 0; for (i = 0; i < n; i++) ws[wv[i]]++; for (i = 1; i < m; i++) ws[i] += ws[i - 1]; for (i = n - 1; i >= 0; i--) sa[--ws[wv[i]]] = y[i]; for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n; i++) x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++; } return; } int rank[maxn], height[maxn]; void calheight(int *r, int *sa, int n) { int i, j, k = 0; for (i = 1; i <= n; i++) rank[sa[i]] = i; for (i = 0; i < n; height[rank[i++]] = k) for (k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++); return; } int RMQ[maxn]; int mm[maxn]; int best[20][maxn]; void initRMQ(int n) { int i, j, a, b; for (mm[0] = -1, i = 1; i <= n; i++) mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1]; for (i = 1; i <= n; i++) best[0][i] = i; for (i = 1; i <= mm ; i++) for (j = 1; j <= n + 1 - (1 << i); j++) { a = best[i - 1][j]; b = best[i - 1][j + (1 << (i - 1))]; if (RMQ[a] < RMQ[b]) best[i][j] = a; else best[i][j] = b; } return; } int askRMQ(int a, int b) { int t; t = mm[b - a + 1]; b -= (1 << t) - 1; a = best[t][a]; b = best[t][b]; return RMQ[a] < RMQ[b] ? a : b; } int lcp(int a, int b) { int t; a = rank[a]; b = rank[b]; if (a > b) {t = a; a = b; b = t;} return (height[askRMQ(a + 1, b)]); } int num[maxn], n; int sa[maxn]; bool check(int k) { int Min = ~0u >> 1, Max = 0; int ans = 0; for (int i = 2; i <=n; i++) { if (height[i] < k) { ans = max(ans, Max - Min); Min = n; Max = 0; continue; } if (height[i - 1] < k) { Min = min(Min, sa[i - 1]); Max = max(Max, sa[i - 1]); } if (height[i]>=k) { Min = min(Min, sa[i]); Max = max(Max, sa[i]); } } ans = max(ans, Max - Min); if (ans >= k) return 1; return 0; } int doit() { int t = 1, w = n; while (w - t > 1) { int mid = (t + w) / 2; if (check(mid)) t = mid; else w = mid; } if (check(w)) return w; if (check(t)) return t; return 0; } int main() { for (;;) { scanf("%d", &n); if (!n) break; for (int i = 0; i < n; i++) scanf("%d", &num[i]); for (int i = 0; i < n - 1; i++) num[i] = num[i + 1] - num[i] + 90; if (n < 10) { puts("0"); continue; } num[--n] = 0; da(num, sa, n + 1, 300); calheight(num, sa, n); int tmp = doit(); if (tmp < 4) printf("0\n"); else printf("%d\n", tmp + 1); } }
相关文章推荐
- 后缀数组(SA倍增算法)
- 后缀数组 DA(倍增)算法求 SA[N] 与 Rank[N] (时间O(NlogN),空间O(N))
- 后缀数组 DA(倍增)算法求 SA[N] 与 Rank[N] (时间O(NlogN),空间O(N))
- [Tyvj 1860] 后缀数组 倍增O(nlogn) 求sa[],height[]模板
- 后缀数组学习笔记——罗穗骞倍增算法代码
- poj1743 Musical Theme 后缀数组的应用(求最长不重叠重复子串)
- 【HDOJ6223】Infinite Fraction Path(后缀数组,倍增)
- 利用倍增算法的后缀数组
- POJ.3145.Common Substrings(后缀数组 倍增 单调栈)
- 后缀数组——罗穗骞倍增算法代码详解
- 后缀数组的倍增算法
- poj1743 Musical Theme(后缀数组+二分判定)
- POJ 2774 Long Long Message(后缀数组:倍增算法)
- poj1743 Musical Theme 后缀数组之不可重叠最长公共子串
- 【倍增后缀数组】 poj1743 &2406& 3261 & 3294 & 2774
- poj1743(后缀数组+二分)
- 后缀数组的学习(二):如何用基数排序来快速构造出SA数组
- [POJ1743]Musical Theme(后缀数组||后缀自动机)
- 后缀数组--学习笔记(倍增算法)
- 后缀数组的倍增模板与DC3模板