感觉最近好混乱......各种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 }