• POJ 1743 Musical Theme


      感觉最近好混乱......各种OJ都刷一点,感觉不太好......尤其是这种英文题

      这道题一开始还没有看懂。听了ljh大犇的解释后终于明白了。下面我为英语和我一样的人翻译一下题面:

      输入n个数。求最长的两端不交叉的序列,使它们的变化量相同,即相邻两位的差相同。当这个长度小于5时输出0。

      好了,这道题是不是和最长不重叠子串有点像?把原数组差分后,简直一模一样。我们先构出原数组的后缀数组,然后二分一个答案(答案显然具有单调性是吧?),扫一遍height数组看一看是否存在后缀i,j,使得lcp(i,j)>=x && abs(len(j)-len(i))>x 。找到了当前答案(x)就是可行的。一路判断下去就可以辣!不过这道题要注意:原数组差分之后只有n-1个!

      下面贴代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout);
     6 #define maxn 200010
     7 
     8 using namespace std;
     9 typedef long long llg;
    10 
    11 int n,ht[maxn],rk[maxn],sa[maxn],c[maxn],a[maxn];
    12 
    13 int getint(){
    14     int w=0;bool q=0;
    15     char c=getchar();
    16     while((c>'9'||c<'0')&&c!='-') c=getchar();
    17     if(c=='-') q=1,c=getchar();
    18     while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
    19     return q?-w:w;
    20 }
    21 
    22 void build_sa(int m){
    23     int i,*x=rk,*y=ht;
    24     for(i=1;i<=m;i++) c[i]=0;
    25     for(i=1;i<=n;i++) c[x[i]=a[i]]++;
    26     for(i=1;i<=m;i++) c[i]+=c[i-1];
    27     for(i=n;i;i--) sa[c[x[i]]--]=i;
    28     for(int k=1,p;k<=n;k<<=1){
    29         p=0;
    30         for(i=n-k+1;i<=n;i++) y[++p]=i;
    31         for(i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k;
    32         for(i=1;i<=m;i++) c[i]=0;
    33         for(i=1;i<=n;i++) c[x[y[i]]]++;
    34         for(i=1;i<=m;i++) c[i]+=c[i-1];
    35         for(i=n;i;i--) sa[c[x[y[i]]]--]=y[i];
    36         swap(x,y); x[sa[1]]=1; p=1;
    37         for(i=2;i<=n;i++)
    38             x[sa[i]]=(y[sa[i-1]]==y[sa[i]] && y[sa[i-1]+k]==y[sa[i]+k])?p:++p;
    39         if(p==n) break; m=p;
    40     }
    41     for(i=1;i<=n;i++) rk[sa[i]]=i;
    42     for(int i=1,j,k=0;i<=n;i++){
    43         if(k) k--;
    44         j=sa[rk[i]-1];
    45         while(a[i+k]==a[j+k]) k++;
    46         ht[rk[i]]=k;
    47     }
    48 }
    49 
    50 bool pd(int x){
    51     for(int i=2,ma,mi;i<=n;){
    52         while(ht[i]<x && i<=n) i++;
    53         ma=mi=sa[i-1];
    54         while(ht[i]>=x && i<=n){
    55             ma=max(ma,sa[i]);
    56             mi=min(mi,sa[i]);
    57             i++;
    58         }
    59         if(ma-mi>x) return 1;
    60     }
    61     return 0;
    62 }
    63 
    64 int main(){
    65     File("a");
    66     n=getint();
    67     while(n){
    68         for(int i=0;i<n;i++) a[i]=getint();
    69         for(int i=n-1;i;i--) a[i]=a[i]-a[i-1]+100;
    70         build_sa(200);
    71         int l=0,r=n+1,mid;
    72         while(l!=r){
    73             mid=l+r>>1;
    74             if(pd(mid)) l=mid+1;
    75             else r=mid;
    76         }
    77         if(l<=4) printf("0
    ");
    78         else printf("%d
    ",l);
    79         n=getint();
    80     }
    81     return 0;
    82 }

      

  • 相关阅读:
    网络
    进程与线程
    JVM学习笔记(四)——Java内存模型和线程安全
    黑马程序员C++学习笔记
    在python中编写一个简单的关于类的情况遇到的问题(待解决)
    Python学习笔记
    项目实战
    老九学堂C++实现小游戏之小公主养成记
    C++实现经典排序算法
    C++学习代码笔记
  • 原文地址:https://www.cnblogs.com/lcf-2000/p/5658425.html
Copyright © 2020-2023  润新知