[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 }
View Code

 

posted @ 2020-10-20 07:26  PYWBKTDA  阅读(85)  评论(0编辑  收藏  举报