Musical Theme POJ

Musical Theme

POJ - 1743

题意:求一段旋律的最长主旋律(不可重叠)。

对给出的旋律做差,求后缀数组。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn=20010;
 7 const int inf=0x3f3f3f3f;
 8 int s[maxn];
 9 int sa[maxn], t1[maxn],t2[maxn],c[maxn];
10 int h[maxn],rank[maxn];
11 int n;
12 void build_sa(int n, int m){
13     int i, *x = t1, *y = t2;
14     for(i = 0; i < m; i++) c[i] = 0;
15     for(i = 0; i < n; i++) c[x[i] = s[i]]++;
16     for(i = 1; i < m; i++) c[i] += c[i-1];
17     for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i;
18 
19     for(int k = 1; k <= n; k <<= 1){
20         int p = 0;
21         for(i = n-k; i < n; i++) y[p++] = i;
22         for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i]-k; 
23         for(i = 0; i < m; i++) c[i] = 0;
24         for(i = 0; i < n; i++) c[x[y[i]]]++;
25         for(i = 1; i< m; i++) c[i] += c[i-1];
26         for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i];
27         swap(x,y);
28         p = 1;
29         x[sa[0]] = 0;
30         for(i = 1; i < n; i++) 
31           x[sa[i]] = y[sa[i]]==y[sa[i-1]] && y[sa[i]+k]==y[sa[i-1]+k]? p-1 : p++;
32         if(p>=n) break;
33         m=p;
34     }
35 }
36 
37 void geth(int n){
38     int i, j, k=0;
39     for(i = 0; i <= n; i++) rank[sa[i]]=i; 
40     for(i = 0; i < n; i++) {
41         if(k) k--;
42         j = sa[rank[i]-1];
43         while(s[i+k]==s[j+k]) k++;
44         h[rank[i]] = k;
45     }
46 }
47 int ck(int k){
48     int minn, maxn;
49     minn=maxn=sa[1];
50     for(int i = 2; i <= n; i++) {
51         if(h[i] >= k){
52             minn = min(minn, sa[i]);
53             maxn = max(maxn, sa[i]);
54             if(maxn-minn >= k) return 1;
55         }else {
56             maxn=minn=sa[i];
57         }
58     }
59     return 0;
60 }
61 int main(){
62     while(scanf("%d",&n)&&n){
63         for(int i = 0; i < n; i++) scanf("%d",&s[i]);
64         for(int i = 0; i < n-1; i++) s[i] = s[i+1]-s[i]+88;
65         s[--n]=0;
66         build_sa(n+1,200);
67         geth(n);
68         int ans=0;
69         int l=4, r=n;
70         while(l <= r) {
71             int m=(l+r)>>1;
72             if(ck(m)) {
73                 ans = m;
74                 l = m+1;
75             } else {
76                 r = m-1;
77             }
78         }
79         ans++;
80         printf("%d
",ans<5? 0:ans); 
81     }
82     
83 }
View Code
原文地址:https://www.cnblogs.com/yijiull/p/7521628.html