1743:Musical Theme
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 }