傳送門c++
分析出題目是讓咱們求兩個最長的重複的不相交的子串。數組
考慮到兩個後綴有相同的前綴就會有那麼長的重複的子串,使用後綴數組。spa
變調什麼的差分一下仍是同樣作。.net
二分答案,同時記錄後綴出現位置,題目保證不相交。注意最後二分出的答案須要+1。code
#include <bits/stdc++.h> using namespace std; const int MAXN=1e5+7; int x[MAXN],y[MAXN],sa[MAXN],c[MAXN],height[MAXN],rk[MAXN],n,m,s[MAXN],a[MAXN]; inline void get_sa() { for(int i=1;i<=n;i++) c[x[i]=s[i]]++; for(int i=2;i<=m;i++) c[i]+=c[i-1]; for(int i=n;i;i--) sa[c[x[i]]--]=i; for(int k=1;k<=n;k<<=1){ int p=0; for(int i=n-k+1;i<=n;i++) y[++p]=i; for(int i=1;i<=n;i++) if(sa[i]>k) y[++p]=sa[i]-k; for(int i=1;i<=m;i++) c[i]=0; for(int i=1;i<=n;i++) c[x[i]]++; for(int i=2;i<=m;i++) c[i]+=c[i-1]; for(int i=n;i;i--) sa[c[x[y[i]]]--]=y[i],y[i]=0; swap(x,y);x[sa[1]]=p=1; for(int i=2;i<=n;i++) x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i-1]+k]==y[sa[i]+k])?p:++p; if(p==n) break; m=p; } } inline void get_height() { for(int i=1;i<=n;i++) rk[sa[i]]=i; int k=0; for(int i=1;i<=n;i++){ if(rk[i]==1) continue; if(k) k--; int j=sa[rk[i]-1]; while(s[i+k]==s[j+k]&&i+k<=n&&j+k<=n) k++; height[rk[i]]=k; } } inline bool check(int x) { int mn=999999999,mx=-1; for(int i=1;i<=n;i++){ if(height[i]>=x){ mn=min(sa[i],mn); mx=max(sa[i],mx); if(mx-mn>x) return 1; } else { mx=mn=sa[i]; } } return 0; } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i];n--; for(int i=1;i<=n;i++) s[i]=(a[i+1]-a[i]+10101); m=20000; get_sa();get_height(); int l=0,r=n; while(l<=r){ int mid=l+r>>1; if(check(mid)) l=mid+1; else r=mid-1; } if(l<5) puts("0"); else printf("%d",l); }