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

posted @ 2016-05-19 22:27  Helica  阅读(114)  评论(0编辑  收藏  举报