POJ 1743:Musical Theme

1743:Musical Theme

Link

meaning of the title

  Given a sequence, find two substrings that satisfy:

  • length of at least 5
  • The same or the same after transpose (transpose: the sequence becomes a sequence after adding and subtracting the same number for each number in the sequence)
  • Two substrings cannot have a common part.

 

ideas

  For the second condition, it is the same after difference (a wonderful transformation). Then it is to find the longest substring of a string that occurs 2 times and cannot overlap.

  The suffix array, divided into a length x, determines whether it is satisfied.

  Judgment: height can be divided into multiple sub-segments (each sub-segment is a continuous sequence and all the values ​​of height must be > x), then for any two of the corresponding suffixes in each sub-segment, the common sub-series > x , so find the leftmost point and the rightmost point in the current subsection, and ask to judge whether they overlap (ie rl>x).

 

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 
 4 using namespace std;
 5 
 6 const int N = 20010;
 7 
 8 int t1[N],t2[N],c[N],height[N],rnk[N],sa[N],s[N],a[N];
 9 int n,m;
10 
11 void get_sa() {
12     m = 180;
13     int *x = t1,*y = t2,p,i;
14     for (i=0; i<m; ++i) c[i] = 0;
15     for (i=0; i<n; ++i) x[i]=s[i],c[x[i]]++;
16     for (i=0; i<m; ++i) c[i] += c[i-1];
17     for (i=n-1; i>=0; --i) sa[--c[x[i]]] = i;
18     for (int k=1; k<=n; k<<=1) {
19         p = 0;
20         for (i=n-k; i<n; ++i) y[p++] = i;
21         for (i=0; i<n; ++i) if (sa[i]>=k) y[p++] = sa[i]-k;
22         for (i=0; i<m; ++i) c[i] = 0;
23         for (i=0; i<n; ++i) c[x[y[i]]]++;
24         for (i=0; i<m; ++i) c[i] += c[i-1];
25         for (i=n-1; i>=0; --i) sa[--c[ x[y[i]] ]] = y[i];
26         swap(x,y);
27         p = 1;
28         x[sa[0]] = 0;
29         for (i=1; i<n; ++i) 
30             x[sa[i]] = y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
31         m = p;
32     }
33 }
34 void get_height() {
35     for (int i=0; i<n; ++i) rnk[sa[i]] = i;
36     int k = 0;
37     height[0] = 0;
38     for (int i=0; i<n; ++i) {
39         if (!rnk[i]) continue;
40         if (k) k--;
41         int j = sa[rnk[i]-1];
42         while (i+k<n && j+k<n && s[i+k]==s[j+k]) k++;
43         height[rnk[i]] = k;
44     }
45 }
46 bool check(int x) {
47     int l = sa[0],r = sa[0];
48     for (int i=1; i<n; ++i) {
49         if (height[i] < x) l = r = sa[i];
50         else {
51             l = min(l,sa[i]);r = max(r,sa[i]);
52             if (r - l >= x) return true; // r-l 不是r-l+1,模拟一下 
53         }
54     }
55     return false;
56 }
57 void solve() {
58     int L = 1,R = n/2,ans = -1;
59     while (L <= R) {
60         int mid = (L + R) / 2;
61         if (check(mid)) ans = mid,L = mid + 1;
62         else R = mid - 1; 
63     }
64     if (ans < 4) puts("0");
65     else printf("%d\n",ans+1);
66 }
67 int main() {
68     while (~scanf("%d",&n) && n){
69         for (int i=0; i<n; ++i) scanf("%d",&a[i]);
70         for (int i=1; i<n; ++i) s[i] = a[i] - a[i-1] + 88;
71         get_sa();
72         get_height();
73         solve();
74     }
75     return 0;
76 }

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325263036&siteId=291194637