标签:相等 memset std 连续 tchar 后缀数组 class for ant
一个数列求对应差相等最长的一段。\(n\leqslant 2\times 10^4\)
后缀数组+二分。
将数列差分一下,一段字符串在\(height\)数组上一定是连续的一段,二分一个答案,找到一段\(>=mid\)的区间,然后记录一下最大最小值。
因为\(mid\)会将他们分成一段段区间,最后判断一下即可。
#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int N = 20050; inline int in(int x=0,char ch=getchar()) { while(ch>‘9‘||ch<‘0‘) ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();return x; } int n,m; int a[N],b[N]; namespace SA { int t1[N],t2[N],c[N],sa[N],rk[N],ht[N]; void clear() { memset(sa,0,sizeof(sa)); memset(rk,0,sizeof(rk)); memset(ht,0,sizeof(ht)); } void get_sa(int a[],int n=::n,int m=::m) { int *x=t1,*y=t2; for(int i=1;i<=m;i++) c[i]=0; for(int i=1;i<=n;i++) c[x[i]=a[i]]++; for(int i=1;i<=m;i++) c[i]+=c[i-1]; for(int i=n;i;--i) sa[c[x[i]]--]=i; for(int k=1,p=0;k<n;k<<=1,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=1;i<=m;i++) c[i]+=c[i-1]; for(int i=n;i;--i) sa[c[x[y[i]]]--]=y[i]; 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]+k]==y[sa[i-1]+k])?p:++p; if(p>=n) break;m=p; } } void get_ht(int a[],int n=::n) { for(int i=1;i<=n;i++) rk[sa[i]]=i; for(int i=1,j,k=0;i<=n;ht[rk[i++]]=k) for(j=sa[rk[i]-1],k=k?k-1:k;a[i+k]==a[j+k];k++); } } using namespace SA; int chk(int x) { for(int i=1,j;i<=n;i=j) { int mi=n,mx=0; if(ht[i]<x) { j=i+1;continue; } mi=min(mi,sa[i-1]),mx=max(mx,sa[i-1]); for(j=i;j<=n && ht[j]>=x;mi=min(mi,sa[j]),mx=max(mx,sa[j]),j++); if(mi+x<=mx) return 1; }return 0; } void Solve() { int l=0,r=n; for(;l<=r;) { int mm=(l+r)>>1; if(chk(mm)) l=mm+1; else r=mm-1; }printf("%d\n",r>3?r+1:0); } int main() { for(;;) { if(!(n=in())) break; for(int i=1;i<=n;i++) b[i]=in(); for(int i=1;i<n;i++) a[i]=b[i+1]-b[i]+100; n--; // n=in(); // for(int i=1;i<=n;i++) a[i]=in(); // for(int i=1;i<=n;i++) cout<<a[i]<<" ";cout<<endl; clear(); get_sa(a,n,200); // cout<<"qwq"<<endl; // for(int i=1;i<=n;i++) cout<<sa[i]<<" ";cout<<endl; get_ht(a,n); // for(int i=1;i<=n;i++) cout<<ht[i]<<" ";cout<<endl; Solve(); }return 0; }
标签:相等 memset std 连续 tchar 后缀数组 class for ant
原文地址:http://www.cnblogs.com/beiyuoi/p/6646324.html