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 }
  • 相关阅读:
    哨兵模式(工作中使用)
    JVM调优-考虑方向
    Spring Cloud Gateway+Nacos出现服务乱串的问题记录
    golang笔记-cache组件应用: freecache/groupcache/golang-lru
    C++优化笔记: -O2/-O3/-ffast-math/SIMD
    linux笔记-查看L1/L2/L3 cache大小
    Dom4j 如何输出 Document 中的内容到文本
    是应该是用 Log 还是 Logger 来定义 Log
    IntelliJ IDEA 如何针对Java 代码快速打印 println
    如何用 Java 判断一个给定的数是不是素数
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/10344549.html
Copyright © 2011-2022 走看看