【最长重复子串问题】
可重叠最长重复子串 -- POJ 3261
题意:给出包含n个元素的数组a,问其中最长可重叠重复子串的长度,要求该子串至少重复k次;输入保证至少存在一个重复k次的最长子串;
难点:二分查找子串的长度,注意对该长度的子串是否存在K个重复子串的判定方法;
代码:
1 /* 2 Problem: POJ 3261 3 Tips: 可重复最长重复子串,后缀数组,二分 4 Time: 172ms 5 Date: 2015.8.31 6 */ 7 #include <iostream> 8 #include <cstring> 9 #include <cstddef> 10 #include <cstdio> 11 #include <string> 12 #include <algorithm> 13 const int maxn = 100005; 14 const int maxm = 1000005; 15 int wa[maxm],wb[maxn],wv[maxn],ws[maxm]; 16 int sa[maxn], rank[maxn],height[maxn]; 17 int cmp(int *rank, int a,int b,int l) 18 { 19 return rank[a]==rank[b] && rank[a+l]==rank[b+l]; 20 } 21 void debug1(int* r, int n) 22 { 23 for(int i = 0; i < n; i++) 24 { 25 printf("sa[%d]: %d\n", i, sa[i]); 26 int p = sa[i]; 27 for(; p < n; p++) 28 printf("%d ", r[p]); 29 printf("\n"); 30 } 31 } 32 void debug2(int* r, int n) 33 { 34 for(int i = 0; i < n; i++) 35 { 36 printf("height[rank[%d]]: %d\n", i, height[rank[i]]); 37 } 38 } 39 void da(int *r,int n,int m) 40 { 41 int i, k, p, *x=wa, *y=wb, *t; 42 for(i=0;i<m;i++) ws[i] = 0; 43 for(i=0;i<n;i++) ws[x[i] = r[i]]++; 44 for(i=1;i<m;i++) ws[i] += ws[i-1]; 45 for(i=n-1;i>=0;i--) sa[--ws[x[i]]] = i; 46 for(k=1, p=1; p<n; k*=2, m=p) 47 { 48 for(p=0,i=n-k;i<n;i++) y[p++]=i; 49 for(i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k; 50 for(i=0;i<n;i++) wv[i]=x[y[i]]; 51 for(i=0;i<m;i++) ws[i]=0; 52 for(i=0;i<n;i++) ws[wv[i]]++; 53 for(i=1;i<m;i++) ws[i]+=ws[i-1]; 54 for(i=n-1;i>=0;i--) sa[--ws[wv[i]]]=y[i]; 55 t=x,x=y,y=t; 56 for(p=1,x[sa[0]]=0,i=1;i<n;i++) 57 x[sa[i]]=cmp(y,sa[i-1],sa[i],k)?p-1:p++; 58 } 59 //debug1(r, n); 60 return; 61 } 62 void calheight(int *r,int n) 63 { 64 int i,j,k=0; 65 for(i=1;i<=n;i++) rank[sa[i]]=i; 66 for(i=0;i<n;height[rank[i++]]=k) 67 for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++) 68 ; 69 //debug2(r, n); 70 return; 71 } 72 bool check(int mid, int n, int k) //Notice! 73 { 74 int i = 1; //height[0] = 0; 75 while(1) 76 { 77 while(i <= n && height[i] < mid) i++; 78 if(i == n+1) break; 79 int cnt = 1; 80 while(i <= n && height[i] >= mid) i++, cnt++; 81 if(cnt >= k) return true; 82 } 83 return false; 84 } 85 int bin_search(int n, int k) 86 { 87 int l = 1, r = n, mid; 88 int ans = 0; 89 while(l <= r) 90 { 91 mid = l+(r-l)/2; 92 if(check(mid, n, k)) 93 ans = mid, l = mid+1; 94 else 95 r = mid-1; 96 } 97 return ans; 98 } 99 int main() 100 { 101 int n, k, r[maxn]; 102 scanf("%d%d", &n, &k); 103 for(int i = 0; i < n; i++) {scanf("%d", &r[i]); r[i]++;} 104 r[n] = 0; 105 da(r,n+1,maxm); 106 calheight(r,n); 107 int ans = bin_search(n, k); 108 printf("%d\n", ans); 109 return 0; 110 }
时间: 2024-10-12 19:22:11