POJ3261-Milk Patterns-后缀数组
可重叠重复k次的最长子串长度。
还是使用二分答案对heigh数组分组的做法。
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #include <vector> 5 #include <iostream> 6 7 using namespace std; 8 const int maxn = 2e4+10; 9 10 int s[maxn]; 11 int sa[maxn],rank[maxn],height[maxn]; 12 13 int t[maxn],t2[maxn],c[maxn]; 14 void build(int n,int m) 15 { 16 int i,j,p,*x = t, *y = t2; 17 18 for(i=0;i<m;i++)c[i]=0; 19 for(i=0;i<n;i++)c[x[i]=s[i]]++; 20 for(i=1;i<m;i++)c[i]+=c[i-1]; 21 for(i=n-1;i>=0;i--)sa[--c[x[i]]]=i; 22 for(j=1;j<=n;j<<=1) 23 { 24 p=0; 25 for(i=n-j;i<n;i++)y[p++]=i; 26 for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j; 27 for(i=0;i<m;i++)c[i]=0; 28 for(i=0;i<n;i++)c[x[y[i]]]++; 29 for(i=1;i<m;i++)c[i]+=c[i-1]; 30 for(i=n-1;i>=0;i--)sa[--c[x[y[i]]]]=y[i]; 31 swap(x,y); 32 p=1;x[sa[0]]=0; 33 for(i=1;i<n;i++) 34 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++; 35 if(p>=n)break; 36 m=p; 37 } 38 n--; 39 int k = 0; 40 for(int i=0;i<=n;i++) rank[sa[i] ] = i; 41 for(int i=0;i<n;i++) 42 { 43 if(k) k--; 44 int j = sa[rank[i]-1]; 45 while(s[i+k]==s[j+k]) k++; 46 height[rank[i] ] = k; 47 } 48 } 49 50 int N,K; 51 52 bool check(int len,int k) 53 { 54 int cnt = 1; 55 for(int i=2;i<=N;i++) 56 { 57 if(height[i] >= len) 58 { 59 cnt++; 60 if(cnt >= k) return true; 61 } 62 else 63 cnt = 1; 64 } 65 return false; 66 } 67 68 int main() 69 { 70 while(~scanf("%d%d",&N,&K)) 71 { 72 int Max = 0; 73 for(int i=0,tmp;i<N;i++) 74 { 75 scanf("%d",&s[i]); 76 Max = max(Max,s[i]); 77 } 78 s[N] = 0; 79 build(N+1,Max+1); 80 81 int l=0,r=N,mid; 82 int ans = 0; 83 84 while(l<=r) 85 { 86 mid = (l+r)>>1; 87 if(check(mid,K)){ 88 l = mid+1; 89 ans = mid; 90 } 91 else 92 r = mid-1; 93 } 94 printf("%d\n",ans); 95 } 96 }
POJ