zoukankan      html  css  js  c++  java
  • P2743(poj1743) Musical Themes[差分+后缀数组]

    P2743 乐曲主题Musical Themes(poj1743)

    然后呢这题思路其实还是蛮简单的,只是细节特别多比较恶心,忘记了差分带来的若干疏漏。
    因为转调的话要保证找到相同主题,只要保证一段内相对的差值不变,所以自然而然想到差分。
    注意细节。
    1.因为差分会带来负数,而负数在后缀数组里最初排名是会出问题的,所以要全搞成正的,+100即可
    2.因为最后一位不可以计算入差分数组里,所以不算,n要减1,同时二分答案后要记得
    把求得的最长差分长度加上一才是原数组长度
    3.最坑的地方是找不重复的最长字串,自然套路二分答案,但check时有部分不一样。
    因为差分会导致下标相减算原串长度出问题,所以要注意,具体看check函数。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=5000+7;
     5 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
     6 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
     7 inline int read(){
     8     int x=0,f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
     9     while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();return f?-x:x;
    10 }
    11 int A[N],a[N],sa[N],rk[N],x[N],y[N],cnt[N],h[N];
    12 int n,m=200,p,L,R,mid,ans;
    13 
    14 inline void suffix_sort(){
    15     for(register int i=1;i<=n;++i)++cnt[x[i]=a[i]];
    16     for(register int i=1;i<=m;++i)cnt[i]+=cnt[i-1];
    17     for(register int i=n;i;--i)sa[cnt[x[i]]--]=i;
    18     for(register int k=1;k<n;k<<=1,p=0){
    19         for(register int i=n-k+1;i<=n;++i)y[++p]=i;
    20         for(register int i=1;i<=n;++i)if(sa[i]>k)y[++p]=sa[i]-k;
    21         for(register int i=1;i<=m;++i)cnt[i]=0;
    22         for(register int i=1;i<=n;++i)++cnt[x[y[i]]];
    23         for(register int i=1;i<=m;++i)cnt[i]+=cnt[i-1];
    24         for(register int i=n;i;--i)sa[cnt[x[y[i]]]--]=y[i];
    25         swap(x,y);x[sa[1]]=p=1;
    26         for(register int i=2;i<=n;++i)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p:++p;
    27         if(p==n)break;m=p;
    28     }p=0;
    29     for(register int i=1;i<=n;++i)rk[i]=x[i];
    30     for(register int i=1;i<=n;h[rk[i]]=p,p?--p:1,++i)while(a[i+p]==a[sa[rk[i]-1]+p]&&++p);
    31 }
    32 
    33 inline int check(int k){
    34     int l=sa[1],r=sa[1];
    35     for(register int i=2;i<=n;++i){
    36         if(h[i]<k)l=r=sa[i];
    37         else{MIN(l,sa[i]),MAX(r,sa[i]);if(r-l>k)return 1;}
    38     }
    39     return 0;
    40 }
    41 
    42 int main(){//freopen("tmp.in","r",stdin);
    43     n=read();L=4,R=n/2+1;
    44     if(n<10){cout<<0<<endl;return 0;}
    45     for(register int i=1;i<=n;++i)A[i]=read();
    46     for(register int i=1;i<n;++i)a[i]=A[i+1]-A[i]+100;--n;
    47     suffix_sort();
    48     while(L<=R){
    49         mid=L+R>>1;
    50         if(check(mid))L=mid+1,ans=mid;
    51         else R=mid-1;//cerr<<mid<<" "<<check(mid)<<endl;
    52     }
    53     printf("%d
    ",ans?ans+1:0);
    54     return 0;
    55 }
  • 相关阅读:
    MySQL Explain学习笔记
    postman测试文件上传接口教程
    URLDecoder异常Illegal hex characters in escape (%)
    第三章 jQuery总结 参考文本
    史上最简单的一道面试题!坑人吧
    cookie和session的关联关系
    服务器配置
    Rancher 添加主机无法显示、添加主机无效的解决办法
    .NET Core 跨平台 串口通讯 ,Windows/Linux 串口通讯,flyfire.CustomSerialPort 的使用
    .Net Core 跨平台应用使用串口、串口通信 ,可能出现的问题、更简洁的实现方法
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10344549.html
Copyright © 2011-2022 走看看