POJ1743---Musical Theme (后缀数组+二分)
题意 :求最长不相交重复子串的长度。。
可以先求出LCP,,对于长度 二分出答案。。(竟然不会写二分)
1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <ctime> 5 #include <queue> 6 #include <stack> 7 #include <cstdio> 8 #include <string> 9 #include <vector> 10 #include <cstdlib> 11 #include <cstring> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 typedef unsigned long long ull; 16 typedef long long ll; 17 const int inf = 0x3f3f3f3f; 18 const double eps = 1e-8; 19 const int maxn = 2e4+10; 20 int sa[maxn], k, len, tmp[maxn], rank[maxn]; 21 int s[maxn]; 22 bool cmp(int i, int j) 23 { 24 if (rank[i] != rank[j]) 25 return rank[i] < rank[j]; 26 else 27 { 28 int x = (i + k <= len ? rank[i+k] : -1); 29 int y = (j + k <= len ? rank[j+k] : -1); 30 return x < y; 31 } 32 } 33 void build_sa() 34 { 35 for (int i = 0; i <= len; i++) 36 { 37 sa[i] = i; 38 rank[i] = i < len ? s[i] : -1; 39 } 40 for (k = 1; k <= len; k *= 2) 41 { 42 sort (sa, sa+len+1, cmp); 43 tmp[sa[0]] = 0; 44 for (int i = 1; i <= len; i++) 45 { 46 tmp[sa[i]] = tmp[sa[i-1]] + (cmp(sa[i-1], sa[i]) ? 1 : 0); 47 } 48 for (int i = 0; i <= len; i++) 49 { 50 rank[i] = tmp[i]; 51 } 52 } 53 } 54 int lcp[maxn]; 55 void Get_lcp() 56 { 57 for (int i = 0; i < len; i++) 58 { 59 rank[sa[i]] = i; 60 } 61 int h = 0; 62 lcp[0] = 0; 63 for (int i = 0; i < len; i++) 64 { 65 int j = sa[rank[i]-1]; 66 if (h > 0) 67 h--; 68 for (; i+h < len && j+h < len; h++) 69 if (s[i+h] != s[j+h]) 70 break; 71 lcp[rank[i]] = h; 72 } 73 } 74 bool check(int m) 75 { 76 int mini = len, maxi = 0; 77 for (int i = 1; i <= len; i++) 78 { 79 if (maxi - mini >= m ) 80 return true; 81 if (lcp[i] < m) 82 { 83 mini = len, maxi = 0; 84 continue; 85 } 86 mini = min(sa[i-1], mini); 87 maxi = max(sa[i-1], maxi); 88 mini = min(sa[i], mini); 89 maxi = max(sa[i], maxi); 90 } 91 return false; 92 } 93 int main() 94 { 95 #ifndef ONLINE_JUDGE 96 freopen("in.txt","r",stdin); 97 #endif 98 int n; 99 while (scanf ("%d", &n), n) 100 { 101 for (int i = 0; i < n; i++) 102 scanf ("%d", s+i); 103 for (int i = 0; i < n-1; i++) 104 s[i] = s[i+1] - s[i] + 89; 105 len = n-1; 106 build_sa(); 107 Get_lcp(); 108 int ua = 0, ub = len; 109 int mid; 110 while (ua+1 < ub) 111 { 112 mid = (ua + ub ) >> 1; 113 if (check(mid) == true) 114 ua = mid; 115 else 116 ub = mid; 117 } 118 ua = (ua < 4 ? 0 : ua + 1); 119 printf("%d\n", ua); 120 } 121 return 0; 122 }