zoukankan      html  css  js  c++  java
  • [bzoj3998][TJOI2015]弦论——后缀自动机

    题目大意:

    给定一个字符串,求它的第k小子串。

    思路:

    后缀自动机的模板题。
    考虑将后缀自动机建出来之后,求出每一个状态在原串中出现了多少次,然后统计以每个节点往后拓展的字符串总共有多少种(按照拓扑序累加即可),最后直接在DAG上做类似二分的就好了。

    /*=======================================
     * Author : ylsoi
     * Time : 2019.2.9
     * Problem : bzoj3998
     * E-mail : ylsoi@foxmail.com
     * ====================================*/
    #include<bits/stdc++.h>
    
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
    #define debug(x) cout<<#x<<"="<<x<<" "
    #define fi first
    #define se second #define mk make_pair
    #define pb push_back
    typedef long long ll;
    
    using namespace std;
    
    void File(){
        freopen("bzoj3998.in","r",stdin);
        freopen("bzoj3998.out","w",stdout);
    }
    
    template<typename T>void read(T &_){
        _=0; T f=1; char c=getchar();
        for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
        for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0');
        _*=f;
    }
    
    const int maxn=5e5+10;
    int n,ty;
    ll m;
    char s[maxn];
    
    struct Suffix_Automaton{
        struct node{
            int len,fa,ch[26];
        }t[maxn<<1];
        int last,tot;
        ll sz[maxn<<1],sum[maxn<<1];
        Suffix_Automaton(){last=tot=1;}
        void insert(int x){
            int p=last,np=last=++tot;
            sz[np]=1;
            t[np].len=t[p].len+1;
            while(p && !t[p].ch[x])t[p].ch[x]=np,p=t[p].fa;
            if(!p)t[np].fa=1;
            else{
                int q=t[p].ch[x];
                if(t[q].len==t[p].len+1)t[np].fa=q;
                else{
                    int nq=++tot;
                    t[nq]=t[q],t[nq].len=t[p].len+1;
                    t[q].fa=t[np].fa=nq;
                    while(p && t[p].ch[x]==q)t[p].ch[x]=nq,p=t[p].fa;
                }
            }
        }
        int tax[maxn<<1],lis[maxn<<1];
        void get_times(){
            if(!ty)REP(i,2,tot)sz[i]=1;
            else{
                REP(i,2,tot)++tax[t[i].len];
                REP(i,1,n)tax[i]+=tax[i-1];
                REP(i,2,tot)lis[tax[t[i].len]--]=i;
                DREP(i,tot-1,1)sz[t[lis[i]].fa]+=sz[lis[i]];
                sz[1]=0;
            }
        }
        bool vis[maxn<<1];
        void get_num(int o){
            if(vis[o])return;
            vis[o]=1;
            sum[o]=sz[o];
            REP(i,0,25){
                int v=t[o].ch[i];
                if(!v)continue;
                get_num(v);
                sum[o]+=sum[v];
            }
        }
        void dfs(int o,ll k){
            k-=sz[o];
            if(k<=0)return;
            REP(i,0,25){
                int v=t[o].ch[i];
                if(!v)continue;
                if(k<=sum[v]){
                    printf("%c",'a'+i);
                    dfs(v,k);
                    break;
                }
                else k-=sum[v];
            }
        }
    }T;
    
    int main(){
    //	File();
        scanf("%s",s+1);
        read(ty),read(m);
        n=strlen(s+1);
        REP(i,1,n)T.insert(s[i]-'a');
        T.get_times();
        T.get_num(1);
        if(T.sum[1]<m)printf("-1");
        else T.dfs(1,m);
        return 0;
    }
    
    
  • 相关阅读:
    第一次作业
    机器学习第一次个人作业
    第02组 Beta版本演示
    第02组 Beta冲刺(4/4)
    第02组 Beta冲刺(3/4)
    微信小程序信息会话列表删除功能
    微信小程序自定义弹窗组件
    微信小程序使用Echarts
    uni.showModal,uni.showToast使用
    Array filter() 方法
  • 原文地址:https://www.cnblogs.com/ylsoi/p/10357631.html
Copyright © 2011-2022 走看看