poj3261 Milk Patterns(后缀数组)

 

【题目链接】

 

  http://poj.org/problem?id=3261

 

【题意】

 

  至少出现k次的可重叠最长子串。

 

【思路】

       二分长度+划分height,然后判断是否存在一组的数目不小于k即可。

       需要注意的是:用末尾添0的方法解决n==1时的RE问题,但是在can中需要忽略height[0]且考虑height[1..n]。

【代码】

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 5 using namespace std;
 6 
 7 const int maxn = 20000+10;
 8 const int maxm = 1000000+10;
 9 
10 int s[maxn];
11 int sa[maxn],c[maxm],t[maxn],t2[maxn];
12 
13 void build_sa(int m,int n) {
14     int i,*x=t,*y=t2;
15     for(i=0;i<m;i++) c[i]=0;
16     for(i=0;i<n;i++) c[x[i]=s[i]]++;
17     for(i=1;i<m;i++) c[i]+=c[i-1];
18     for(i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
19     
20     for(int k=1;k<=n;k<<=1) {
21         int p=0;
22         for(i=n-k;i<n;i++) y[p++]=i;
23         for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
24         
25         for(i=0;i<m;i++) c[i]=0;
26         for(i=0;i<n;i++) c[x[y[i]]]++;
27         for(i=0;i<m;i++) c[i]+=c[i-1];
28         for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
29         
30         swap(x,y);
31         p=1; x[sa[0]]=0;
32         for(i=1;i<n;i++) 
33             x[sa[i]]=y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
34         if(p>=n) break;
35         m=p;
36     }
37 }
38 int rank[maxn],height[maxn];
39 void getHeight(int n) {
40     int i,j,k=0;
41     for(i=0;i<=n;i++) rank[sa[i]]=i;
42     for(i=0;i<n;i++) {
43         if(k) k--;
44         j=sa[rank[i]-1];
45         while(s[j+k]==s[i+k]) k++;
46         height[rank[i]]=k;
47     }
48 }
49 
50 int n,k;
51 
52 bool can(int limit) {
53     int cnt=1;                //忽略height[0] 截至height[n]
54     for(int i=2;i<=n;i++) {    
55         if(height[i]>=limit) {
56             if(++cnt>=k) return true;
57         }
58         else cnt=1;
59     }
60     return false;
61 }
62 
63 int main() {
64     scanf("%d%d",&n,&k);
65     int up=0;
66     FOR(i,0,n-1) {
67          scanf("%d",&s[i]);
68          s[i]++;
69          up=max(up,s[i]);
70     }
71     s[n]=0;
72     build_sa(up+1,n);
73     getHeight(n);
74     int L=0,R=n;
75     while(L<R) {
76         int M=L+(R-L+1)/2;
77         if(can(M)) L=M;
78         else R=M-1;
79     }
80     printf("%d
",L);
81     return 0;
82 }
原文地址:https://www.cnblogs.com/lidaxin/p/5002310.html