poj 3261

后缀数组,还是对height数据进行分组。然后二分答案。

 1 #include <iostream>
 2      #include <cstdio>
 3      #include <cstring>
 4      #include <map>
 5      using namespace std;
 6      const int maxn=20000+10;
 7      int num[maxn];
 8      int sa[maxn],t[maxn],t2[maxn],c[maxn],height[maxn],rank[maxn];
 9      map<int,int> a;
10      int n,K;
11      void build_sa(int m,int n,int *s)
12      {
13          int i,*x=t,*y=t2;
14          for(i=1;i<m;i++) c[i]=0;
15          for(i=0;i<n;i++) c[x[i]=a[s[i]]]++;
16          for(i=2;i<m;i++) c[i]+=c[i-1];
17          for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
18          for(int k=1;k<=n;k<<=1)
19          {
20              int p=0;
21              for(i=n-k;i<n;i++) y[p++]=i;
22              for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
23              for(i=1;i<m;i++) c[i]=0;
24              for(i=0;i<n;i++) c[x[y[i]]]++;
25              for(i=2;i<m;i++) c[i]+=c[i-1];
26              for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
27              swap(x,y);
28              p=2;x[sa[0]]=1;
29              for(i=1;i<n;i++) x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
30              if(p>n) break;
31              m=p;
32          }
33      }
34      void getHeight(int n)
35      {
36          int i,j,k=0;
37          for(i=0;i<n;i++) rank[sa[i]]=i;
38          for(i=0;i<n;i++)
39          {
40              if(k) k--;
41              if(rank[i])
42              {
43                  int j=sa[rank[i]-1];
44                  while(num[i+k]==num[j+k]) k++;
45                  height[rank[i]]=k;
46              }
47          }
48      }
49      int bsearch(int n)
50      {
51          int low=3,high=n+1,mid,i,cou;
52          int flag;
53          while(high>low)
54          {
55              flag=0;
56              cou=1;
57              mid=low+(high-low)/2;
58              for(i=1;i<n;i++)
59              {
60                  if(height[i]>=mid) cou++;
61                  else
62                  {
63                      if(cou>=K)
64                      {
65                          flag=1;
66                          break;
67                      }
68                      cou=1;
69                  }
70              }
71              if(cou>=K) flag=1;
72              if(flag) low=mid+1;
73              else high=mid;
74          }
75          return low-1;
76      }
77      int main()
78      {
79          //freopen("1.txt","r",stdin);
80          scanf("%d%d",&n,&K);
81              int i,tem,tot=1;
82              for(i=0;i<n;i++)
83              {
84                  scanf("%d",&num[i]);
85                  if(!a[num[i]]) a[num[i]]=tot++;
86              }
87              build_sa(tot,n,num);
88              getHeight(n);
89              int ans=bsearch(n);
90              printf("%d\n",ans);
91          return 0;
92      }
93  
原文地址:https://www.cnblogs.com/lj030/p/3112439.html