先求后缀数组、相邻两个后缀的最长公共前缀
二分答案,o(n)check
1 #include<algorithm> 2 #include<iostream> 3 #include<cstdlib> 4 #include<cstring> 5 #include<cstdio> 6 #include<string> 7 #include<cmath> 8 #include<ctime> 9 #include<queue> 10 #include<stack> 11 #include<map> 12 #include<set> 13 #define rre(i,r,l) for(int i=(r);i>=(l);i--) 14 #define re(i,l,r) for(int i=(l);i<=(r);i++) 15 #define Clear(a,b) memset(a,b,sizeof(a)) 16 #define inout(x) printf("%d",(x)) 17 #define douin(x) scanf("%lf",&x) 18 #define strin(x) scanf("%s",(x)) 19 #define LLin(x) scanf("%lld",&x) 20 #define op operator 21 #define CSC main 22 typedef unsigned long long ULL; 23 typedef const int cint; 24 typedef long long LL; 25 using namespace std; 26 void inin(int &ret) 27 { 28 ret=0;int f=0;char ch=getchar(); 29 while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();} 30 while(ch>='0'&&ch<='9')ret*=10,ret+=ch-'0',ch=getchar(); 31 ret=f?-ret:ret; 32 } 33 int n,s[100010],t[100010],t2[100010],c[1000010],sa[100010]; 34 void build_sa(int m) 35 { 36 int *x=t,*y=t2,p=0; 37 re(i,0,n-1)x[i]=s[i],c[x[i]]++; 38 re(i,1,m-1)c[i]+=c[i-1]; 39 rre(i,n-1,0)sa[--c[x[i]]]=i; 40 for(int k=1;k<=n;k<<=1) 41 { 42 rre(i,n-1,n-k)y[++p]=i; 43 re(i,0,n-1)if(sa[i]>k)y[p++]=sa[i]-k; 44 Clear(c,0); 45 re(i,0,n-1)c[x[y[i]]]++; 46 re(i,1,m-1)c[i]+=c[i-1]; 47 rre(i,n-1,0)sa[--c[x[y[i]]]]=i; 48 swap(x,y);p=1; 49 re(i,1,n-1)x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]]==y[sa[i]-1]?p-1:p++; 50 if(p>=n)break; 51 m=p; 52 } 53 return ; 54 } 55 int height[100010]; 56 void build_height() 57 { 58 static int rank[100010]; 59 re(i,0,n-1)rank[sa[i]]=i; 60 height[rank[0]]=0; 61 int k=0; 62 re(i,0,n-1) 63 { 64 if(k)k--; 65 if(!rank[i])continue; 66 int j=sa[rank[i]-1]; 67 while(s[i+k]==s[j+k])k++; 68 height[rank[i]]=k; 69 } 70 } 71 bool check(int k) 72 { 73 int shu=0; 74 re(i,1,n-1) 75 { 76 if(height[i]>=k)shu++; 77 else 78 { 79 if(shu+1>=k)return 1; 80 shu=0; 81 } 82 } 83 if(shu+1>=k)return 1; 84 return 0; 85 } 86 int main() 87 { 88 inin(n); 89 re(i,0,n-1)inin(s[i]); 90 build_sa(1000000); 91 build_height(); 92 int l=0,r=n+1; 93 while(l<r-1) 94 { 95 int mid=(l+r)>>1; 96 if(check(mid))l=mid; 97 else r=mid; 98 } 99 cout<<l; 100 return 0; 101 }