• CF1063F String Journey


    http://codeforces.com/problemset/problem/1063/F

    题解

    首先我们注意到对于任意一种划分,我们都可以把它调整长度为((len,len-1,len-2....1))的。所以我们可以用(( t{第一个串的位置,第一个串的长度}))来表示一个划分。

    所以我们可以设(dp[i][j])表示((i,j))这种方案是否可行,转移是从后往前的,可以用哈希,因为第二维是根号级别的,所以复杂度为(nsqrt{n})

    发现若有(dp[i][j]),那么就有(dp[i][j-1]),我们可以换一种状态设计令(dp[i])表示最大的合法的(j)

    若要判断((i,j))是否合法,我们需要在((i+j,n))中找到(lcp(i,x)geq j-1 ||lcp(i+1,x)geq j-1),这个可以用后缀数组+主席树在(logn)的时间内判断。

    这个东西可以二分,但是我们发现(dp[i]leq dp[i+1]+1),于是我们的判断次数就变成(O(n))的了。

    代码

    #include<bits/stdc++.h>
    #define N 500009
    #define inf 1e9
    #define ls tr[cnt].l
    #define rs tr[cnt].r
    using namespace std;
    typedef long long ll;
    char s[N];
    int n,tong[N],y[N],rnk[N],sa[N],dp[N],p[21][N],h[N],m,Log[N],tott,T[N];
    inline ll rd(){
        ll x=0;char c=getchar();bool f=0;
        while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
        while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
        return f?-x:x;
    }
    struct seg{
        int l,r,mx;
    }tr[N*21];
    int query(int cnt,int l,int r,int L,int R){
        if(!cnt)return 0;
        if(l>=L&&r<=R)return tr[cnt].mx;
        int mid=(l+r)>>1,ans=0;
        if(mid>=L)ans=max(ans,query(ls,l,mid,L,R));
        if(mid<R)ans=max(ans,query(rs,mid+1,r,L,R));
        return ans;
    }
    void upd(int &cnt,int pre,int l,int r,int x,int y){
        cnt=++tott;tr[cnt]=tr[pre];
        if(l==r){
          tr[cnt].mx=y;
          return;
        }
        int mid=(l+r)>>1;
        if(mid>=x)upd(ls,tr[pre].l,l,mid,x,y);
        else upd(rs,tr[pre].r,mid+1,r,x,y);
        tr[cnt].mx=max(tr[ls].mx,tr[rs].mx);
    }
    inline int lcp(int l,int r){
        if(l>r)swap(l,r);
        if(l==r)return inf;
        l++;
        int lo=Log[r-l+1];
        return min(p[lo][l],p[lo][r-(1<<lo)+1]);
    }
    inline void qsort(){
        for(int i=0;i<=m;++i)tong[i]=0;
        for(int i=1;i<=n;++i)tong[rnk[i]]++;
        for(int i=1;i<=m;++i)tong[i]+=tong[i-1];
        for(int i=n;i>=1;--i)sa[tong[rnk[y[i]]]--]=y[i];
    }
    inline void SA(){
        m=200;
        for(int i=1;i<=n;++i)rnk[i]=s[i],y[i]=i;
        qsort();
        for(int w=1,p=0;p<n;w<<=1,m=p){
            p=0;
            for(int i=n-w+1;i<=n;++i)y[++p]=i;
            for(int i=1;i<=n;++i)if(sa[i]>w)y[++p]=sa[i]-w;
            qsort();
            swap(rnk,y);
            rnk[sa[1]]=p=1;
            for(int i=2;i<=n;++i)
                rnk[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+w]==y[sa[i-1]+w])?p:++p;
        }
        for(int i=1;i<=n;++i){
            if(rnk[i]==1)continue;
            int y=max(0,h[rnk[i-1]]-1);
            while(s[i+y]==s[sa[rnk[i]-1]+y])y++;
            h[rnk[i]]=p[0][rnk[i]]=y;
        }
        for(int i=1;(1<<i)<=n;++i)
            for(int j=1;j+(1<<i)-1<=n;++j)
                p[i][j]=min(p[i-1][j],p[i-1][j+(1<<i-1)]);
    }
    inline bool pd(int x,int len){
        int l=rnk[x],r=n,ansr=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(lcp(rnk[x],mid)>=len-1)ansr=mid,l=mid+1;
            else r=mid-1;
        }
        l=1;r=rnk[x];
        int ansl=n+1;
        while(l<=r){
            int mid=(l+r)>>1;
            if(lcp(mid,rnk[x])>=len-1)ansl=mid,r=mid-1;
            else l=mid+1;
        }
        if(ansl<=ansr)if(query(T[x+len],1,n,ansl,ansr)>=len-1)return 1;
        x++;
        l=rnk[x],r=n,ansr=0;
        while(l<=r){
            int mid=(l+r)>>1;
            if(lcp(rnk[x],mid)>=len-1)ansr=mid,l=mid+1;
            else r=mid-1;
        }
        l=1;r=rnk[x];
        ansl=n+1;
        while(l<=r){
            int mid=(l+r)>>1;
            if(lcp(mid,rnk[x])>=len-1)ansl=mid,r=mid-1;
            else l=mid+1;
        }
        if(ansl<=ansr)if(query(T[x+len-1],1,n,ansl,ansr)>=len-1)return 1;
        return 0;
    }
    int main(){
        n=rd();
        scanf("%s",s+1);
        for(int i=2;i<=n;++i)Log[i]=Log[i>>1]+1;
        SA();
        int ans=0;
        for(int i=n;i>=1;--i){
           int mx=dp[i+1]+1;
           while(!pd(i,mx))mx--;
           dp[i]=mx;
           upd(T[i],T[i+1],1,n,rnk[i],mx);
           ans=max(ans,dp[i]);
        }
        cout<<ans;
        return 0;
    }
    
  • 相关阅读:
    Vue.js
    docker搭建pxc
    mkvirtualenv管理python版本
    gitlab
    centos7安装kvm及kvm管理
    centos7安装docker
    【从NIO到Netty】8.零拷贝案例2-网络传输
    【从NIO到Netty】7.零拷贝案例1-复制文件
    【从NIO到Netty】6.零拷贝介绍
    【从NIO到Netty】5.NIO EchoServer
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/11001681.html
Copyright © 2020-2023  润新知