可重叠的k次最长重复子串
题目链接: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 }