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 }

 

posted on 2016-07-19 20:14  pb2016  阅读(150)  评论(0编辑  收藏  举报