• EOJ 7月月赛


    EOJ 7月月赛

    D. 给你一个字符串,你现在需要的是将它的每一个前缀看成单独的字符串,最终组成最大的一个整数。

    ​ 分析,可以想到,两个前缀A,B组成的字符串,其大小由相对顺序决定,不妨设|A|<|B|。B=A+X,则最终的大小取决于A+X于X+A的字典序大小。这个直接通过SA就可以解决。最终通过排序来解决。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 100005;
    
    const int MOD = 998244353;
    
    int sa[N], rk[N], c[N], h[N], x[N], y[N];
    
    int rmq[N][21], n, base=10;
    
    int lg[N], pw[N], arr[N], val[N];
    
    char s[N];
    
    void SA(){
        int m=256;
        for(int i=1;i<=m;++i)c[i]=0;
        for(int i=1;i<=n;++i)++c[x[i]=s[i]];
        for(int i=1;i<=m;++i)c[i]+=c[i-1];
        for(int i=n;i>=1;--i)sa[c[s[i]]--]=i;
    
        for(int k=1,p;k<=n;k<<=1){
            p=0;
            for(int i=n;i>n-k;--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>=1;--i)sa[c[x[y[i]]]--]=y[i];
    
            p=y[sa[1]]=1;
            for(int i=2,a,b;i<=n;++i){
                a=(sa[i]+k>n?-1:x[sa[i]+k]);
                b=(sa[i-1]+k>n?-1:x[sa[i-1]+k]);
    
                y[sa[i]]=(x[sa[i]]==x[sa[i-1]]&&a==b?p:++p);
            }
    
            if(p>=n)break;
    
            m=p;
            swap(x,y);
        }
    
        for(int i=1;i<=n;++i){
            rk[sa[i]]=i;
        }
    }
    
    void getHeight(){
        for(int i=1, k=0;i<=n;++i){
            if(k)--k;
            int j=sa[rk[i]-1];
            while(s[i+k]==s[j+k])++k;
            h[rk[i]]=k;
        }
    }
    
    void init(){
        SA();
        getHeight();
    
        for(int i=1;i<=n;++i)rmq[i][0]=h[i];
        for(int j=1;j<=20;++j){
            for(int i=1;i+(1<<j)-1<=n;++i){//bug
                rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<j-1)][j-1]);
            }
        }
    }
    
    int LCP(int l, int r){
        l=rk[l];r=rk[r];
        ++l,++r;
        if(l>r)swap(l,r);
        --r;
    
        int k=lg[r-l+1];
        return min(rmq[l][k],rmq[r-(1<<k)+1][k]);
    }
    
    
    bool cmp(int l, int r){
        if(l>r)return !cmp(r,l);
    
        int c=LCP(1,l+1);
        int len=r-l;
    
        if(c<len){
            return rk[l+1]<rk[1];
        }else{
            return rk[1]<rk[len+1];
        }
    }
    
    int main(){
        lg[0]=-1;
        for(int i=1;i<=100000;++i)lg[i]=lg[i>>1]+1;
        scanf("%s", s+1);
        n=strlen(s+1);
        init();
    
        pw[0]=1;
        for(int i=1;i<=n;++i){
            val[i]=(1ll*val[i-1]*base+s[i]-'0')%MOD;
            pw[i]=1ll*pw[i-1]*base%MOD;
            arr[i]=i;
        }
    
        sort(arr+1,arr+n+1,cmp);
    
        int ans=0;
        for(int i=1;i<=n;++i)ans=(1ll*ans*pw[arr[i]]+val[arr[i]])%MOD;
    
        if(ans<0)ans+=MOD;
    
        printf("%d",ans);
    
        return 0;
    }
    
    

    其他题都没啥营养,咕咕咕。

  • 相关阅读:
    记录一次电话面试
    记录一次git合并
    HTML通用属性与常见标签
    位运算的应用
    HTML总结
    前端MVC
    常用软件
    docker常用命令
    composer install(update)时出现killed
    优化小技巧:该怎么识别百度蜘蛛呢
  • 原文地址:https://www.cnblogs.com/JohnRan/p/13360151.html
Copyright © 2020-2023  润新知