• bzoj3998: [TJOI2015]弦论


    传送门

    一道后缀自动机的简单题;

    对串建立后缀自动机,然后基排算每个点的right集合大小,它能到达的点集的大小,它能到达的点集的right集合大小。

    然后直接在自动机上跑就好了。

    //Achen
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<ctime>
    const int N=1e6+7;
    typedef long long LL;
    using namespace std;
    int T,k,len,cnt;
    char s[N],ans[N];
    
    template<typename T> void read(T &x) {
        T f=1; x=0; char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
        if(ch=='-') f=-1,ch=getchar();
        for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    }
    
    int rt=1,tot=1,last=1,ch[N][26],fa[N],ln[N];
    LL sz[N],sz2[N],sum[N],summ;
    void insert(int x) {
        int p=last,np=++tot; last=np;
        ln[np]=ln[p]+1; sz2[np]=1;
        for(;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;
        if(!p) fa[np]=rt;
        else {
            int q=ch[p][x];
            if(ln[q]==ln[p]+1) fa[np]=q;
            else {
                int nq=++tot; ln[nq]=ln[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q]; fa[q]=fa[np]=nq; 
                for(;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;
            }
        }
    }
    
    void calc() {
        static int c[N],sa[N];
        for(int i=2;i<=tot;i++) c[ln[i]]++;
        for(int i=2;i<=len;i++) c[i]+=c[i-1];
        for(int i=2;i<=tot;i++) sa[c[ln[i]]--]=i;
        for(int i=tot-1;i>=1;i--) {
            int x=sa[i],y=fa[x];
            sz2[y]+=sz2[x];
            for(int j=0;j<26;j++) {
                sum[x]+=sum[ch[x][j]];
                sz[x]+=sz[ch[x][j]];
            }
            sum[x]+=sz2[x];
            sz[x]++;
        }
        for(int i=0;i<26;i++) 
        summ+=sz[ch[rt][i]]; 
    }
    
    int travel(int k) {
        int x=rt;
        while(k) {
            for(int i=0;i<26;i++) {
                int y=ch[x][i];
                if(sz[y]>=k) {
                    ans[cnt++]='a'+i;
                    if(T==0) k--;
                    else k-=sz2[y];
                    k=max(k,0);
                    x=y;
                    break;
                }
                else {
                    if(T==0) k-=sz[y];
                    else k-=sum[y];
                }
            }
        } 
    }
    
    int main() {
        scanf("%s",s);
        read(T); read(k);
        len=strlen(s);
        for(int i=0;i<len;i++) insert(s[i]-'a');
        calc();
        if((T==1&&len*(len+1)/2<k)||(T==0&&summ<k)) {
            puts("-1");
            return 0;
        }
        travel(k);
        puts(ans);
        return 0;
    }
    View Code
  • 相关阅读:
    NLTK学习笔记(三):NLTK的一些工具
    NLTK学习笔记(四):自然语言处理的一些算法研究
    NLTK学习笔记(五):分类和标注词汇
    深入C++的运算符重载
    python3实现TCP协议的简单服务器和客户端
    python3实现UDP协议的简单服务器和客户端
    Windows平台下python2和3的兼容问题解决
    异常处理
    内置方法
    反射:hasattr、getattr、setattr、delattr
  • 原文地址:https://www.cnblogs.com/Achenchen/p/8206809.html
Copyright © 2020-2023  润新知