poj 3261 Milk Patterns
http://poj.org/problem?id=3261
题意:求一个整数序列最长的重复k次的序列,序列可以重叠。
思路:后缀数组+二分:得到height数组后,二分答案ans,检查height数据里是否有连续的k-1个值不小于ans。

#include<set> #include<map> #include<stack> #include<queue> #include<cmath> #include<bitset> #include<string> #include<climits> #include<cstdio> #include<vector> #include<utility> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define IN puts("in") #define OUT puts("out") #define FR(x) freopen(x,"r",stdin) #define FW(x) freopen(x,"w",stdout) #define MSET(x,y) memset(x,y,sizeof(x)) #define ST system("pause") #define NU(x) (x[0]*1000+x[1]*100+x[2]*10+x[3]) using namespace std; const int maxn = 22005; int wn[maxn],wa[maxn],wb[maxn],wv[maxn],a[maxn],sa[maxn],Rank[maxn],height[maxn]; char r[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) wn[i] = 0; for(i = 0; i < n; ++ i) wn[x[i]=r[i]]++; for(i = 1; i < m; ++ i) wn[i] += wn[i-1]; for(i = n - 1; i >= 0; --i) sa[--wn[x[i]]] = i; for(p = 1,j = 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 < m; ++ i) wn[i] = 0; for(i = 0; i < n; ++ i) wn[wv[i]=x[y[i]]]++; for(i = 1; i < m; ++ i) wn[i] += wn[i-1]; for(i = n - 1; i >= 0; --i) sa[--wn[wv[i]]] = y[i]; for(t = x,x = y,y = t,x[sa[0]] = 0,p=1,i=1; i<n; ++i) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; } } void calheight(int *r,int *sa,int n) { int i,j,k = 0; for(i = 1; i <= n; ++ i){ Rank[sa[i]] = i; height[i] = 0;} 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); } int check(int val,int rep,int n) { int k = 1; for(int i = 2; i <= n; ++ i){ if(height[i]>=val){ k++; }else{ if(k>=rep)return 1; k = 1; } } if(k>=rep)return 1; return 0; } int main() { int i,j,k,n,m; while(scanf("%d %d",&n,&m)==2) { set<int>mset; set<int>::iterator pos; map<int,int>mmap; for(i = 0; i < n; ++ i){ scanf("%d",a+i); mset.insert(a[i]); } pos = mset.begin(); for(i = 1; pos != mset.end(); ++ pos,++i) mmap[*pos] = i; for(i = 0; i < n; ++ i)a[i] = mmap[a[i]]; a[n] = 0; da(a,sa,n+1,mset.size()+3); calheight(a,sa,n); // for(i = 1; i <= n; ++ i)printf("%d ",height[i]);puts(""); int low = 0,high = n,mid; k = 0; while(low<=high){ mid = (low+high) >> 1; if(check(mid,m,n)){ low = mid + 1; k = mid; }else high = mid - 1; } printf("%d\n",k); }return 0; }