题目链接:https://cn.vjudge.net/contest/318888#problem/B

 

题意:

约翰注意到奶牛产奶的之类是不断变化的,虽然他不能预测从当天到下一天的变化情况但是他知道变化是有规律的,牛奶的质量由一个整数表示,范围从0到1000000,现在给定一个长度为n的序列,要求找到一个最大子序列,该子序列重复出现至少k次,各个出现部分可有重叠,求最长的长度。简单来说就是可重叠的k 次最长重复子串。

简单来说就是求可重叠的k次最长重复子串 

 

思路:

这题首先先看数据的范围,发现相差的有点大,所以我们先对数据进行离散化

离散化之后,其实这题和求不可重叠的最长重复子串的思想都是一样的。

如果仔细体会了height的分组的思想,那么不难知道这题其实就是要根据要求分组后该组的个数>=k

 

  1 #include <stdio.h>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <math.h>
  7 #include <queue>
  8 #include <set>
  9 
 10 #define INF 0x3f3f3f3f
 11 #define pii pair<int,int>
 12 #define LL long long
 13 using namespace std;
 14 typedef unsigned long long ull;
 15 const int maxn = 2e6+6;
 16 
 17 int s[maxn];
 18 int sa[maxn],t[maxn],t2[maxn],c[maxn];
 19 int Rank[maxn],height[maxn];
 20 
 21 void build_sa(int n,int m)
 22 {
 23     int i,j,*x=t,*y=t2;
 24     for (i=0;i<m;i++)
 25         c[i] = 0;
 26     for (i=0;i<n;i++)
 27         c[x[i] = s[i]]++;
 28     for (i=1;i<m;i++)
 29         c[i] += c[i-1];
 30     for (i=n-1;i>=0;i--)
 31         sa[--c[x[i]]] = i;
 32     for (int k=1;k<=n;k<<=1)
 33     {
 34         int p = 0;
 35         for (i=n-k;i<n;i++)
 36             y[p++] = i;
 37         for (i=0;i<n;i++)
 38         {
 39             if (sa[i]>=k)
 40                 y[p++] = sa[i]-k;
 41         }
 42         for (i=0;i<m;i++)
 43             c[i] = 0;
 44         for (i=0;i<n;i++)
 45             c[x[y[i]]]++;
 46         for (i=1;i<m;i++)
 47             c[i] += c[i-1];
 48         for (i=n-1;i>=0;i--)
 49             sa[--c[x[y[i]]]] = y[i];
 50         swap(x,y);
 51         p = 1;
 52         x[sa[0]] = 0;
 53         for (i=1;i<n;i++)
 54             x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;
 55         if (p>=n)
 56             break;
 57         m = p;
 58     }
 59 }
 60 
 61 
 62 void getHeight(int n){
 63     int i,j,k=0;
 64     for (i=1;i<=n;i++){
 65         Rank[sa[i]] = i;
 66     }
 67     for (i=0;i<n;i++){
 68         if (k)
 69             k--;
 70         j = sa[Rank[i]-1];
 71         while (s[i+k] == s[j+k])
 72             k++;
 73         height[Rank[i]] = k;
 74     }
 75 }
 76 
 77 int n,k;
 78 int b[maxn];
 79 
 80 void Discretization(){
 81     for (int i=0;i<=n;i++){
 82         b[i] = s[i];
 83     }
 84     sort(b,b+n+1);
 85     int size = unique(b,b+n+1)-b;
 86     for (int i=0;i<=n;i++){
 87         s[i] = lower_bound(b,b+size,s[i])-b;
 88     }
 89 }
 90 
 91 bool check(int x){
 92     int tot = 1;
 93     for (int i=1;i<=n;i++){
 94         if (height[i]>=x)
 95             tot++;
 96         else{
 97             if (tot>=k)
 98                 return true;
 99             tot = 1;
100         }
101     }
102     return tot>=k;
103 }
104 
105 int main(){
106     while (~scanf("%d%d",&n,&k)){
107         for (int i=0;i<n;i++){
108             scanf("%d",&s[i]);
109         }
110         s[n] = 0;
111         Discretization();
112         build_sa(n+1,n+1);
113         getHeight(n);
114         int l=0,r=n,mid;
115         while (l<=r){
116             mid = (l+r)>>1;
117             if (check(mid)){
118                 l = mid+1;
119             }
120             else{
121                 r = mid-1;
122             }
123         }
124         printf("%d\n",r);
125     }
126     return 0;
127 }

 

 

  1 #include <stdio.h>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <string.h>
  5 #include <stdlib.h>
  6 #include <math.h>
  7 #include <queue>
  8 #include <set>
  9 
 10 #define INF 0x3f3f3f3f
 11 #define pii pair<int,int>
 12 #define LL long long
 13 using namespace std;
 14 typedef unsigned long long ull;
 15 const int MAXN = 2e5 + 10;
 16 
 17 int wa[MAXN], wb[MAXN], wv[MAXN], ws_[MAXN];
 18 int sta[MAXN];
 19 int cnt[MAXN];
 20 void Suffix(int *r, int *sa, int n, int m)
 21 {
 22     int i, j, k, *x = wa, *y = wb, *t;
 23     for(i = 0; i < m; ++i) ws_[i] = 0;
 24     for(i = 0; i < n; ++i) ws_[x[i] = r[i]]++;
 25     for(i = 1; i < m; ++i) ws_[i] += ws_[i - 1];
 26     for(i = n - 1; i >= 0; --i) sa[--ws_[x[i]]] = i;
 27     for(j = 1, k = 1; k < n; j *= 2, m = k)
 28     {
 29         for(k = 0, i = n - j; i < n; ++i) y[k++] = i;
 30         for(i = 0; i < n; ++i) if(sa[i] >= j) y[k++] = sa[i] - j;
 31         for(i = 0; i < n; ++i) wv[i] = x[y[i]];
 32         for(i = 0; i < m; ++i) ws_[i] = 0;
 33         for(i = 0; i < n; ++i) ws_[wv[i]]++;
 34         for(i = 1; i < m; ++i) ws_[i] += ws_[i - 1];
 35         for(i = n - 1; i >= 0; --i) sa[--ws_[wv[i]]] = y[i];
 36         t = x;
 37         x = y;
 38         y = t;
 39         for(x[sa[0]] = 0, i = k = 1; i < n; ++i)
 40             x[sa[i]] = (y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j]) ? k - 1 : k++;
 41     }
 42 }
 43 int Rank[MAXN], height[MAXN], sa[MAXN], r[MAXN];
 44 int s[MAXN];
 45 int b[MAXN];
 46 int indexx[MAXN],vis[200];
 47 void calheight(int *r,int *sa,int n)
 48 {
 49     int i,j,k=0;
 50     for(i=1; i<=n; i++)Rank[sa[i]]=i;
 51     for(i=0; i<n; height[Rank[i++]]=k)
 52         for(k?k--:0,j=sa[Rank[i]-1]; r[i+k]==r[j+k]; k++);
 53 }
 54 
 55 bool check(int x,int n,int k){
 56     int tot = 1;
 57     for (int i=1;i<n;i++){
 58         if (height[i]>=x){
 59             tot++;
 60         }
 61         else {
 62             if (tot>=k)
 63                 return true;
 64             tot = 1;
 65         }
 66     }
 67     return tot>=k;
 68 }
 69 
 70 void Discretization(int n){
 71     for (int i=0;i<=n;i++){
 72         b[i] = s[i];
 73     }
 74     sort(b,b+n+1);
 75     int size = unique(b,b+n+1)-b;
 76     for (int i=0;i<=n;i++){
 77         s[i] = lower_bound(b,b+size,s[i])-b;
 78     }
 79 }
 80 
 81 
 82 int main(){
 83     int n,k;
 84     while (~scanf("%d%d",&n,&k) ){
 85         for (int i=0;i<n;i++){
 86             scanf("%d",&s[i]);
 87         }
 88         s[n] = 0;
 89         Discretization(n);
 90         for (int i=0;i<=n;i++)
 91             r[i] = s[i];
 92         Suffix(r,sa,n+1,n+1);
 93         calheight(r,sa,n);
 94         int L=1,R=n,len=0;
 95         while (L<=R){
 96             int mid = (L+R)>>1;
 97             if (check(mid,n+1,k)){
 98                 len = mid;
 99                 L = mid+1;
100             } else
101                 R = mid-1;
102         }
103         printf("%d\n",len);
104     }
105     return 0;
106 }