zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    第十四周课程总结&实验报告(简单记事本的实现)
    第十三周课程总结
    第十二周
    第十一周课程总结
    第十周课程总结
    第九周课程总结&实验报告(七)
    第八周课程总结&实验报告(六)
    第七周课程总结&实验报告(五)
    第六周&java实验报告四
    课程总结
  • 原文地址:https://www.cnblogs.com/yijiull/p/7521628.html
Copyright © 2011-2022 走看看