题目大意:给你一个数组,求这个数组里面至少重复k次的子串。
分析:后缀数组的练手题目...不过给的数字比较大,可以先离散化处理一下即可。
代码如下:
===============================================================================================================================
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int MAXN = 2e4+7; struct SuffixArr { int tempx[MAXN], tempy[MAXN], text[MAXN], Hash[MAXN]; int rank[MAXN], sa[MAXN], sum[MAXN], height[MAXN]; int *x, *y, N, MaxId; void GetText(int data[], int len) { N = len, x=tempx, y=tempy; for(int i=0; i<N; i++) Hash[i] = data[i]; sort(Hash, Hash+N); MaxId = unique(Hash, Hash+N) - Hash; for(int i=0; i<N; i++) { text[i] = x[i] = lower_bound(Hash, Hash+MaxId, data[i])-Hash; y[i] = i; } } bool cmp(int i, int len) { if(sa[i]+len > N || sa[i-1]+len > N) return false; if(y[sa[i]]!=y[sa[i-1]] || y[sa[i]+len]!=y[sa[i-1]+len]) return false; return true; } void BaseSort() { for(int i=0; i<MaxId; i++) sum[i] = 0; for(int i=0; i<N; i++) sum[ x[ y[i] ] ] += 1; for(int i=1; i<MaxId; i++) sum[i] += sum[i-1]; for(int i=N-1; i>=0; i--) sa[ --sum[ x[ y[i] ] ] ] = y[i]; } void GetSa() { BaseSort(); for(int len=1; len <= N; len<<=1) { int id = 0; for(int i=N-len; i<N; i++) y[id++] = i; for(int i=0; i<N; i++)if(sa[i] >= len) y[id++] = sa[i] - len; BaseSort(); swap(x, y); x[ sa[0] ] = id = 0; for(int i=1; i<N; i++) { if(cmp(i, len) == true) x[sa[i]] = id; else x[sa[i]] = ++id; } MaxId = id+1; if(MaxId >= N) break; } } void GetHeight() { for(int i=0; i<N; i++) rank[sa[i]] = i; /// debug(text); /// debug(rank); for(int k=0, i=0; i<N; i++) { if(!rank[i]) { height[0] = k = 0; continue; } if(k)k--; int pre = sa[ rank[i]-1 ]; while(text[i+k] == text[pre+k]) k++; height[rank[i]] = k; } ///debug(height); } void debug(int p[]) { for(int i=0; i<N; i++) printf("%d ", p[i]); printf("\n"); } }; SuffixArr suf; int data[MAXN]; bool Find(int times, int k) { int cnt=0; for(int i=0; i<suf.N; i++) { if(suf.height[i] < k) cnt = 0; else { cnt += 1; if(cnt == times-1) return true; } } return false; } int main() { int N, times; while(scanf("%d%d", &N, ×) != EOF) { for(int i=0; i<N; i++) scanf("%d", &data[i]); data[N] = -1; suf.GetText(data, N+1); suf.GetSa(); suf.GetHeight(); int L=0, R=N, ans=0; while(L <= R) { int Mid = (L+R)>>1; if(Find(times, Mid) == true) { ans = Mid; L = Mid + 1; } else R = Mid - 1; } printf("%d\n", ans); } return 0; }
时间: 2024-10-29 19:09:52