[cf1063F]String Journey
设$f[i]$表示令$s=s[i,n]$且强制$u_{1}$为空所对应的答案,不难发现有$f[i]\le f[i+1]+1$,暴力判断答案,时间复杂度为$o(n\cdot 判断复杂度)$
判断$f[i]$能否等于$k$,当且仅当存在$j$使得$j\ge i+k$、$f[j]\ge k-1$且$max(lcp(i,j),lcp(i+1,j))\ge k-1$,那么最终答案即为$\max(f_{i})$
这个可以用后缀数组来求,对于第3个条件保证其是线段树上的一个区间,第1个条件用可持久化线段树来维护并求出最大的$f[j]$即可,时间复杂度为$o(n\log_{2}n)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define L (k<<1) 5 #define R (L+1) 6 #define mid (l+r>>1) 7 int V,n,ans,a[N],b[N],rk[N<<1],sa[N],h[N],f[N],r[N],mn[N<<2],ls[N*20],rs[N*20],mx[N*20]; 8 char s[N]; 9 bool cmp(int x,int y,int i){ 10 return (rk[x]==rk[y])&&(rk[x+i]==rk[y+i]); 11 } 12 void calc(){ 13 for(int i=0;i<n;i++)rk[i]=s[i]-'a'+1; 14 int m=26; 15 for(int i=1;i<n;i*=2){ 16 memset(a,0,sizeof(a)); 17 a[0]=i; 18 for(int j=i;j<n;j++)a[rk[j]]++; 19 for(int j=1;j<=m;j++)a[j]+=a[j-1]; 20 for(int j=n-1;j>=0;j--)b[a[rk[i+j]]--]=j; 21 memset(a,0,sizeof(a)); 22 for(int j=0;j<n;j++)a[rk[j]]++; 23 for(int j=1;j<=m;j++)a[j]+=a[j-1]; 24 for(int j=n;j;j--)sa[a[rk[b[j]]]--]=b[j]; 25 m=0; 26 for(int j=1;j<=n;j++) 27 if ((j>1)&&(cmp(sa[j-1],sa[j],i)))a[sa[j]]=m; 28 else a[sa[j]]=++m; 29 memcpy(rk,a,sizeof(a)); 30 if (n==m)break; 31 } 32 for(int i=0,j=0;i<n;h[rk[i++]]=j){ 33 if (rk[i]==1)continue; 34 if (j)j--; 35 for(int k=sa[rk[i]-1];(max(i,k)+j<n)&&(s[i+j]==s[k+j]);j++); 36 } 37 h[1]=0; 38 } 39 void build(int k,int l,int r){ 40 if (l==r){ 41 mn[k]=h[l]; 42 return; 43 } 44 build(L,l,mid); 45 build(R,mid+1,r); 46 mn[k]=min(mn[L],mn[R]); 47 } 48 int query(int k,int l,int r,int x,int y){ 49 if ((l>y)||(x>r))return 0x3f3f3f3f; 50 if ((x<=l)&&(r<=y))return mn[k]; 51 return min(query(L,l,mid,x,y),query(R,mid+1,r,x,y)); 52 } 53 int query1(int k,int l,int r,int x,int y){//求在x左边第一个比y小的数 54 if ((l>x)||(mn[k]>=y))return 0; 55 if (l==r)return l; 56 int ans=query1(R,mid+1,r,x,y); 57 if (ans)return ans; 58 return query1(L,l,mid,x,y); 59 } 60 int query2(int k,int l,int r,int x,int y){//求x右边第一个比y小的数 61 if ((r<x)||(mn[k]>=y))return n+1; 62 if (l==r)return l; 63 int ans=query2(L,l,mid,x,y); 64 if (ans<=n)return ans; 65 return query2(R,mid+1,r,x,y); 66 } 67 void update(int &k,int l,int r,int x,int y){ 68 mx[++V]=max(mx[k],y); 69 ls[V]=ls[k]; 70 rs[V]=rs[k]; 71 k=V; 72 if (l==r)return; 73 if (x<=mid)update(ls[k],l,mid,x,y); 74 else update(rs[k],mid+1,r,x,y); 75 } 76 int get(int k,int l,int r,int x,int y){ 77 if ((!k)||(l>y)||(x>r))return 0; 78 if ((x<=l)&&(r<=y))return mx[k]; 79 return max(get(ls[k],l,mid,x,y),get(rs[k],mid+1,r,x,y)); 80 } 81 int main(){ 82 scanf("%d%s",&n,s); 83 calc(); 84 build(1,1,n); 85 ans=f[n-1]=1; 86 update(r[n-1],1,n,rk[n-1],1); 87 for(int i=n-2;i>=0;i--){ 88 f[i]=f[i+1]+1; 89 while (1){ 90 int l=query1(1,1,n,rk[i],f[i]-1),rr=query2(1,1,n,rk[i]+1,f[i]-1)-1; 91 if (get(r[i+f[i]],1,n,l,rr)>=f[i]-1)break; 92 l=query1(1,1,n,rk[i+1],f[i]-1),rr=query2(1,1,n,rk[i+1]+1,f[i]-1)-1; 93 if (get(r[i+f[i]],1,n,l,rr)>=f[i]-1)break; 94 f[i]--; 95 } 96 r[i]=r[i+1]; 97 update(r[i],1,n,rk[i],f[i]); 98 ans=max(ans,f[i]); 99 } 100 printf("%d",ans); 101 }