1 /*********************************************************** 2 题目: Milk Patterns(poj 3261) 3 链接: http://poj.org/problem?id=3261 4 题意: 给一串数字,求这些数字中公共子串个数大于k的 5 最长串。 6 算法: 后缀数组+二分 7 ***********************************************************/ 8 #include<iostream> 9 #include<cstdio> 10 #include<cstring> 11 #include<algorithm> 12 using namespace std; 13 14 const int mx=20010; 15 int s[mx],sa[mx],t[mx],t2[mx],c[mx*50],n,k; 16 int rank[mx],height[mx]; 17 18 void build_sa(int m) 19 { 20 int i,*x=t,*y=t2; 21 for (i=0;i<m;i++) c[i]=0; 22 for (i=0;i<n;i++) c[x[i]=s[i]]++; 23 for (i=1;i<m;i++) c[i]+=c[i-1]; 24 for (i=n-1;i>=0;i--) sa[--c[x[i]]]=i; 25 for (int k=1;k<=n;k<<=1) 26 { 27 int p=0; 28 for (i=n-k;i<n;i++) y[p++]=i; 29 for (i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k; 30 for (i=0;i<m;i++) c[i]=0; 31 for (i=0;i<n;i++) c[x[y[i]]]++; 32 for (i=1;i<m;i++) c[i]+=c[i-1]; 33 for (i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i]; 34 swap(x,y); 35 p=1; 36 x[sa[0]]=0; 37 for (i=1;i<n;i++) 38 x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++; 39 if (p>=n) break; 40 m=p; 41 } 42 } 43 44 void getHeight() 45 { 46 int i,j,k=0; 47 for (i=0;i<n;i++) rank[sa[i]]=i; 48 for (i=0;i<n-1;i++) 49 { 50 if (k) k--; 51 int j=sa[rank[i]-1]; 52 while (s[i+k]==s[j+k]) 53 { 54 k++; 55 } 56 height[rank[i]]=k; 57 58 } 59 } 60 61 bool check(int len) 62 { 63 int i=0; 64 while (i<n) 65 { 66 while (i<n&&height[i]<len) i++; 67 if (i>=n) return false; 68 int cut=1; 69 while (height[i]>=len) 70 { 71 cut++; 72 i++; 73 } 74 if (cut>=k) return true; 75 } 76 return false; 77 } 78 79 int getans() 80 { 81 int l=1,r=n-1; 82 int ans=1; 83 while (l<=r) 84 { 85 int m=(l+r)/2; 86 if (check(m)) 87 { 88 l=m+1; 89 ans=m; 90 } 91 else r=m-1; 92 } 93 return ans; 94 } 95 96 int main() 97 { 98 scanf("%d%d",&n,&k); 99 for (int i=0;i<n;i++) 100 { 101 scanf("%d",&s[i]); 102 } 103 s[n]=0; 104 n++; 105 build_sa(1000001); 106 getHeight(); 107 int ans=getans(); 108 printf("%d\n",ans); 109 }
时间: 2024-10-25 23:15:23