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 }

 

你可能感兴趣的:(theme)