POJ 1743 后缀数组
2017-09-12 16:53
120 查看
简略题意:求不可重叠的最长重复子串。
这题有以下坑点。
1. 给出的n个数不是我们要处理的串,差方之后的串才是。
2. 不可重叠指的是原数组之间不可重叠,例如”1 2 3 4 5 6 7 8 9”的答案为0,而不是5。
注意之后,我们只需要二分答案k,按height不小于k分组,存在一组最大最小位置差大于k即可(不能为k,理由见坑点2)。
复杂度O(nlogn)。
这题有以下坑点。
1. 给出的n个数不是我们要处理的串,差方之后的串才是。
2. 不可重叠指的是原数组之间不可重叠,例如”1 2 3 4 5 6 7 8 9”的答案为0,而不是5。
注意之后,我们只需要二分答案k,按height不小于k分组,存在一组最大最小位置差大于k即可(不能为k,理由见坑点2)。
复杂度O(nlogn)。
#include <iostream> #include <cstring> #include <map> #include <cstdio> using namespace std; struct SuffixArray{ static const int maxn = 1e6+7; int s[maxn], n, m; int sa[maxn], rank[maxn], height[maxn]; int t[maxn], t2[maxn], c[maxn]; int MIN[maxn][30]; void build_sa(){ s[n++] = 0; int *x = t, *y = t2; for(int i=0; i<m; i++) c[i] = 0; for(int i=0; i<n; i++) c[x[i]=s[i]]++; for(int i=1; i<m; i++) c[i]+=c[i-1]; for(int i=n-1; i>=0; i--) sa[--c[x[i]]] = i; for(int k=1; k<=n; k<<=1){ int p = 0; for(int i=n-k; i<n; i++) y[p++] = i; for(int i=0; i<n; i++) if(sa[i]>=k) y[p++] = sa[i]-k; for(int i=0; i<m; i++) c[i] = 0; for(int i=0; i<n; i++) c[x[y[i]]]++; for(int i=1; i<m; i++) c[i]+=c[i-1]; for(int i=n-1; i>=0; i--) sa[--c[x[y[i]]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(int 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; } n--; } void getheight(){ int k = 0; for(int i=1; i<=n; i++) rank[sa[i]] = i; for(int i=0; i<n; i++){ if(k) k --; int j = sa[rank[i]-1]; while(s[i+k] == s[j+k]) k++; height[rank[i]] = k; } } void RMQ_init(){ for(int i=0; i<n; i++) MIN[i][0] = height[i+1]; for(int j=1; (1<<j)<=n; j++){ for(int i=0; i+(1<<j)<=n; i++){ MIN[i][j] = min(MIN[i][j-1], MIN[i+(1<<(j-1))][j-1]); } } } int RMQ(int L, int R){ int k = 0; while((1<<(k+1)) <= R-L+1) k++; return min(MIN[L][k], MIN[R-(1<<k)+1][k]); } int LCP(int i, int j){ if(rank[i] > rank[j]) swap(i, j); return RMQ(rank[i], rank[j]-1); } void init(int *str, int _n){ m = 300; n = _n; memset(height, 0, sizeof height); for(int i=0; i<n; i++) s[i] = (int)str[i]; build_sa(); getheight(); RMQ_init(); } int check(int x) { int minv = sa[1], maxv = sa[1]; for(int i = 2; i <= n; i++) { if(height[i] >= x) { minv = min(minv, sa[i]); maxv = max(maxv, sa[i]); if(maxv - minv > x) { return 1; } } else { minv = sa[i]; maxv = sa[i]; } } return maxv - minv > x; } void solve() { int l = 0, r = n + 1, m; while(l < r) { m = (l + r) >> 1; if(check(m)) l = m + 1; else r = m; } if(l >= 5) printf("%d\n", l); else printf("0\n"); } }suffix; map<int, int> M; int n, cnt, ct; int str[22000]; int main() { while(~scanf("%d", &n) && n) { M.clear(); ct = 0; cnt = 1; int pv = -89; for(int i = 1; i <= n; i++) { int v; scanf("%d", &v); int val = v - pv + 100; pv = v; str[ct++] = val; } suffix.init(str, ct); suffix.solve(); } return 0; }
相关文章推荐
- poj 1743 Musical Theme 后缀数组
- poj 1743 Musical Theme(后缀数组)
- POJ 1743 (后缀数组+不重叠最长重复子串)
- POJ 1743 Musical Theme 后缀数组
- POJ-1743-Musical Theme(后缀数组)
- POJ 1743 Musical Theme(后缀数组)
- POJ 1743 Musical Theme (后缀数组)
- poj 1743 后缀数组+二分答案
- POJ 1743 后缀数组
- POJ 1743 Musical Theme(后缀数组)
- POJ 1743 Musical Theme 后缀数组
- [POJ 1743]Musical Theme(后缀数组)
- Musical Theme POJ - 1743 后缀数组
- poj 1743 Musical Theme (二分+后缀数组)
- POJ 1743 Musical Theme 后缀数组
- POJ 1743 后缀数组
- POJ 1743 Musical Theme(后缀数组)
- POJ 1743 Musical Theme(后缀数组)
- POJ 1743 Musical Theme(二分+后缀数组)
- A - Musical Theme POJ - 1743(后缀数组)