【后缀数组】SPOJ REPEATS
2015-02-12 14:11
363 查看
先存代码,题解之后再传。
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; const int MAXN = 50000,MAXM = 128; int n,len; const int maxlog = 20; char a[MAXN +10]; int rank[MAXN +10],sa[MAXN +10],end[MAXN +10],nsa[MAXN +10],trank[MAXN +10]; int h[MAXN +10],f[MAXN+10][30]; bool cmpr(int i,int j) { if(trank[i] == trank[j]) { if(i+len >= n) return 1; else if(j + len >= n) return 0; return trank[i+len] < trank[j+len]; } return trank[i] < trank[j]; } void calc_sa() { int i; for(i = 0;i < MAXM;i++) end[i] = 0; for(i = 0;i < n;i++) end[a[i]]++; for(i = 1;i < MAXM;i++) end[i] += end[i-1]; for(i = 0;i < n;i++) rank[i] = a[i] > 0?end[a[i]-1]:0; for(i = 0;i < n;i++) sa[--end[a[i]]] = i; for(int k = 1;k < n;k <<= 1) { int ok = 1; len = k; for(i = 0;i < n;i++) end[rank[sa[i]]] = i; for(i = n - 1;i >= 0;i--) { if(sa[i] >= len) nsa[end[rank[sa[i]-len]]--] = sa[i]-len; } for(i = n - len;i < n;i++) { nsa[end[rank[i]]--] = i; } for(i = 0;i < n;i++) { trank[i] = rank[i]; sa[i] = nsa[i]; } rank[sa[0]] = 0; for(int i = 1;i < n;i++) { if(!cmpr(sa[i-1],sa[i]) && !cmpr(sa[i],sa[i-1])) { rank[sa[i]] = rank[sa[i-1]]; ok = 0; } else { rank[sa[i]] = i; } } if(ok) break; } /* for (int i=0;i<n;i++) printf("rank[%d]=%d\n",i,rank[i]); for(int i=0;i<n;i++) printf("%d=%d\n",i,sa[i]); */ } void get_height() { int i,j,k = 0; for(int i = 0; i < n; i++) rank[sa[i]] = i; for(i = 0;i < n;i++) { if(k) k--; if(rank[i]) { j = sa[rank[i] - 1]; while(a[i+k] == a[j+k]) k++; h[rank[i]] = k; } } } void init_RMQ() { int i,j; memset(f,0,sizeof(f)); for(i = 0;i < n;i++) f[i][0] = h[i]; for(j = 1;j < 20;j++) for(i = 0;i + (1 << j) <= n;i++) f[i][j] = min(f[i][j-1], f[i+(1<<(j-1))][j-1]); } int lcp(int a,int b) { int x = rank[a],y = rank[b]; if(x > y) swap(x,y); x++; int k = (int)(log(y-x+1.0) / log(2.0));//log(y - x + 1) return min(f[x][k], f[y-(1 << k)+1][k]); } int main() { int T,i,l,st,ans; for(scanf("%d",&T);T;T--) { scanf("%d",&n); for(i = 0;i < n;i++) scanf(" %c",&a[i]); a = 0; ans = 0; calc_sa(); get_height(); init_RMQ(); for(l = 1;l < n;l++) for(st = 0;st + l < n;st += l) { int k = lcp(st, st+l); if(k < l) continue; int times = k / l + 1; int t = st - (l - k % l); if(t >= 0 && lcp(t, t + l) >= l) times++; ans = max(ans,times); } printf("%d\n",ans); } } /* 1 17 b a b b a b a a b a a b a a b a b */
相关文章推荐
- SPOJ-REPEATS之后缀数组
- HiHocoder1419 : 后缀数组四·重复旋律4&[SPOJ]REPEATS:Repeats
- HiHocoder1419 : 后缀数组四·重复旋律4&[SPOJ]REPEATS:Repeats
- SPOJ 687 Repeats 后缀数组+暴力+rmq
- 【后缀数组】【不同子串个数】DISUBSTR spoj694/705
- 【后缀数组】【spoj 220】Relevant Phrases of Annihilation
- SPOJ SUBST1 New Distinct Substrings 后缀数组-子串个数
- 【后缀数组求重复次数最多的连续重复子串】SPOJ687 POJ3693
- 【SPOJ705】New Distinct Substrings 后缀数组
- spoj 7258 Lexicographical Substring Search(后缀数组 | 后缀自动机)
- [广义后缀自动机 set启发式合并 || dfs序 树状数组 离线] BZOJ 2780 [Spoj]8093 Sevenk Love Oimaster
- spoj 705后缀数组
- spoj 220 Relevant Phrases of Annihilation (后缀数组 每个串中都至少出现两次的不重叠最长子串)
- SPOJ SUBST1 - New Distinct Substrings(后缀数组[不相同的子串的个数])
- 【SPOJ-DISUBSTR】Distinct Substrings【后缀数组】
- [SPOJ220]PHRASES(后缀数组+二分)
- SPOJ 694 705 后缀数组
- spoj694,spoj705 后缀数组/不相同的子串的个数 计算贡献
- 后缀数组(不相同的子串个数)——SPOJ 705
- [后缀数组]spoj694 Distinct Substrings/spoj705 New Distinct Substrings