首页 > 技术文章 > POJ 1743 Musical Theme

lcf-2000 2016-07-10 19:57 原文

  感觉最近好混乱......各种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\n");
78         else printf("%d\n",l);
79         n=getint();
80     }
81     return 0;
82 }

  

推荐阅读