zoukankan      html  css  js  c++  java
  • Musical Theme

    题目大意:

    * 有N(1 <= N <=20000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,现在要找一个重复的主题。 * “主题”是整个音符序列的一个子串,它需要满足如下条件: * 1.长度至少为5个音符 * 2.在乐曲中重复出现(可能经过转调,“转调”的意思是主题序列中每个音符都被加上或减去了同一个整数值。) * 3.重复出现的同一主题不能有公共部分。

     

    分析:也是看的论文才做的这道题,学了4天的后缀数组,终于A掉一道题了,啥也不说了,都是眼泪(怎么做可以看看论文,说的很详细)。

     

    代码如下:

    ===============================================================================================================

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    
    const int MAXN = 2e4+7;
    const int BaseNum = 90;
    
    struct SuffixArr
    {
        int text[MAXN], tempx[MAXN], tempy[MAXN];
        int sum[MAXN], rank[MAXN], sa[MAXN], heigh[MAXN];
        int *x, *y, N, MaxId;
    
        void Insert(int mus[], int len)
        {
            N = len, MaxId = 200;
            x = tempx, y=tempy;
    
            for(int i=0; i<N; i++)
            {
                x[i] = text[i] = mus[i];
                y[i] = i;
            }
        }
        void BaseSort()
        {
            for(int i=0; i<MaxId; i++)
                sum[i] = 0;
            for(int i=0; i<N; i++)
                sum[ x[ y[i] ] ] += 1;
            for(int i=1; i<MaxId; i++)
                sum[i] += sum[i-1];
            for(int i=N-1; i>=0; i--)
                sa[ --sum[ x[ y[i] ] ] ] = y[i];
        }
        bool OK(int i, int len)
        {
            if(sa[i]+len>N || sa[i-1]+len>N)
                return false;
            if(y[sa[i]] != y[sa[i-1]] || y[sa[i]+len] != y[sa[i-1]+len])
                return false;
    
            return true;
        }
        void Build_Sa()
        {
            BaseSort();
    
            for(int len=1; len<N; len<<=1)
            {
                int id = 0;
    
                for(int i=N-len; i<N; i++)
                    y[id++] = i;
                for(int i=0; i<N; i++)if(sa[i]>=len)
                    y[id++] = sa[i] - len;
    
                BaseSort();
                swap(x, y);
    
                x[ sa[0] ] = id = 0;
    
                for(int i=1; i<N; i++)
                {
                    if(OK(i, len) == true)
                        x[ sa[i] ] = id;
                    else
                        x[ sa[i] ] = ++id;
                }
    
                MaxId = id+1;
    
                if(MaxId >= N)break;
            }
        }
        void GetHeight()
        {
            for(int i=0; i<N; i++)
                rank[ sa[i] ] = i;
    
            for(int k=0,i=0; i<N; i++)
            {
                if(!rank[i])
                {
                    k = heigh[0] = 0;
                    continue;
                }
                if(k)k--;
    
                int pre = sa[ rank[i]-1 ];
    
                while(text[pre+k] == text[i+k])
                    k++;
                heigh[rank[i]] = k;
            }
        }
    };
    
    struct SuffixArr suf;
    int music[MAXN];
    
    bool Find(int k)
    {
        int Min, Max;
    
        Min = Max = suf.sa[0];
    
        for(int i=1; i<suf.N; i++)
        {
            if(suf.heigh[i] < k)
                Min = Max = suf.sa[i];
            else
            {
                Min = min(Min, suf.sa[i]);
                Max = max(Max, suf.sa[i]);
    
                if(Max-Min > k)
                    return true;
            }
        }
    
        return false;
    }
    
    int main()
    {
        int i, N;
    
        while(scanf("%d", &N), N)
        {
            for(i=0; i<N; i++)
            {
                scanf("%d", &music[i]);
                if(i)music[i-1] = music[i-1]-music[i]+BaseNum;
            }
            music[N-1] = 0;
    
            suf.Insert(music, N);
            suf.Build_Sa();
            suf.GetHeight();
    
            int L=4, R=N/2, ans=-1;
    
            while(L <= R)
            {
                int Mid = (L+R)>>1;
    
                if(Find(Mid) == true)
                {
                    L = Mid + 1;
                    ans = Mid;
                }
                else
                    R = Mid - 1;
            }
    
            printf("%d
    ", ans+1);
        }
    
        return 0;
    }
  • 相关阅读:
    ASP.NET网站和ASP.NET应用程序的区别
    客户端状态的优缺点
    Web.config配置文件的优点
    ASP.NET中视图状态的优点和缺点
    java常见集合及其用途
    java Socket编程(一)
    java Soket编程(三)
    浏览器到服务器端进行通信的简单理解
    ant 常用命令
    切记,切忌!——转载(收藏以备用)
  • 原文地址:https://www.cnblogs.com/liuxin13/p/4781576.html
Copyright © 2011-2022 走看看