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
", ua);
120     }
121     return 0;
122 }
原文地址:https://www.cnblogs.com/oneshot/p/4342816.html