题目大意:
给定一个数组,求一个最大的长度的子串至少出现过k次
一个子串出现多次,也就是说必然存在2个子串间的前缀长度为所求的值
通过二分答案,通过线性扫一遍,去判断出现次数,也就是说每次遇见一个height[i] , 出现次数就加1,否则重置为1
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 using namespace std; 5 const int N = 20010; 6 int rank[N] , sa[N] , height[N]; 7 int wa[N] , wb[N] , wsf[N] , wv[N]; 8 int a[N]; 9 10 int cmp(int *r , int a , int b , int l) 11 { 12 return r[a]==r[b] && r[a+l]==r[b+l]; 13 } 14 15 void getSa(int *r , int *sa , int n , int m) 16 { 17 int i,j,p; 18 int *x=wa , *y=wb , *t; 19 for(i=0 ; i<m ; i++) wsf[i]=0; 20 for(i=0 ; i<n ; i++) wsf[x[i]=r[i]]++; 21 for(i=1 ; i<m ; i++) wsf[i] += wsf[i-1]; 22 for(i=n-1 ; i>=0 ; i--) sa[--wsf[x[i]]]=i; 23 24 p=1; 25 for(j=1 ; p<n ; j*=2 , m=p){ 26 for(p=0 , i=n-j ; i<n ; i++) y[p++]=i; 27 for(i=0 ; i<n ; i++) if(sa[i]>=j) y[p++]=sa[i]-j; 28 29 for(i=0 ; i<n ; i++) wv[i]=x[y[i]]; 30 for(i=0 ; i<m ; i++) wsf[i]=0; 31 for(i=0 ; i<n ; i++) wsf[wv[i]]++; 32 for(i=1 ; i<m ; i++) wsf[i]+=wsf[i-1]; 33 for(i=n-1 ; i>=0 ; i--) sa[--wsf[wv[i]]]=y[i]; 34 35 t=x,x=y,y=t; 36 x[sa[0]]=0; 37 for(p=1 , i=1 ; i<n ; i++) 38 x[sa[i]] = cmp(y , sa[i-1] , sa[i] , j)?p-1:p++; 39 } 40 return ; 41 } 42 43 void getHeight(int *r , int *sa , int n) 44 { 45 for(int i=1 ; i<=n ; i++) rank[sa[i]]=i; 46 int k=0; 47 int j; 48 for(int i=0 ; i<n ; height[rank[i++]]=k) 49 for(k?k--:0 , j=sa[rank[i]-1] ; r[i+k]==r[j+k] ; k++); 50 return; 51 } 52 53 bool check(int m , int n , int k) 54 { 55 int cnt=1; 56 for(int i=1 ; i<=n ; i++){ 57 if(height[i]>=m){ 58 cnt++; 59 // cout<<"here: "<<m<<" "<<sa[i]<<" "<<sa[i-1]<<endl; 60 if(cnt>=k) return true; 61 } 62 else {cnt=1;if(cnt>=k) return true;} 63 } 64 return false; 65 } 66 67 int main() 68 { 69 // freopen("a.in" , "r" , stdin); 70 int n,k; 71 while(~scanf("%d%d" , &n , &k)) 72 { 73 int maxn =0 ; 74 for(int i=0 ; i<n ; i++){ 75 scanf("%d" , a+i); 76 a[i]++; 77 maxn = max(maxn , a[i]); 78 } 79 a[n]=0; 80 getSa(a , sa , n+1 , maxn+1); 81 getHeight(a , sa , n); 82 83 int l=0 , r=n , ans=0; 84 while(l <= r){ 85 int m=(l+r)>>1; 86 if(check(m,n,k)){ 87 ans = m; 88 l=m+1; 89 }else r=m-1; 90 } 91 printf("%d\n" , ans); 92 } 93 return 0; 94 }