zoukankan      html  css  js  c++  java
  • [TJOI2015]弦论

    题目描述

    为了提高智商,ZJY开始学习弦论。这一天,她在《 String theory》中看到了这样一道问题:对于一个给定的长度为n的字符串,求出它的第k小子串是什么。你能帮帮她吗?

    输入输出格式

    输入格式:

    第一行是一个仅由小写英文字母构成的字符串s

    第二行为两个整数t和k,t为0则表示不同位置的相同子串算作一个,t为1则表示不同位置的相同子串算作多个。k的意义见题目描述。

    输出格式:

    输出数据仅有一行,该行有一个字符串,为第k小的子串。若子串数目不足k个,则输出-1。

    输入输出样例

    输入样例#1: 
    aabc
    0 3
    输出样例#1: 
    aab
    输入样例#2: 
    aabc
    1 3
    输出样例#2: 
    aa
    输入样例#3: 
    aabc
    1 11
    输出样例#3: 
    -1

    说明

    数据范围

    对于10%的数据,n ≤ 1000。

    对于50%的数据,t = 0。

    对于100%的数据,n ≤ 5 × 10^5, t < 2, k ≤ 10^9。

    建出后缀自动机之后,记录一下每个节点有多少个可以到达的字串。。

    t=0的时候每个节点的权值是1,否则就是它的right集合的大小。。

    然后一遍dfs预处理之后再扫一遍就可以得到答案了。。。

    #include<bits/stdc++.h>
    #define ll long long
    #define maxn 2000050
    using namespace std;
    int a[maxn],c[maxn],pre=1;
    int f[maxn],ch[maxn][26],cnt=1;
    int l[maxn],siz[maxn],n,k,t;
    ll tot[maxn];
    char s[maxn];
    
    inline void ins(int x){
        int p=pre,np=++cnt;
        pre=np,l[np]=l[p]+1;
        siz[np]=1;
        
        for(;p&&!ch[p][x];p=f[p]) ch[p][x]=np;
        if(!p) f[np]=1;
        else{
            int q=ch[p][x];
            if(l[q]==l[p]+1) f[np]=q;
            else{
                int nq=++cnt;
                l[nq]=l[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                f[nq]=f[q];
                f[q]=f[np]=nq;
                for(;ch[p][x]==q;p=f[p]) ch[p][x]=nq;
            }
        }
    }
    
    inline void build(){
        for(int i=0;i<n;i++) ins(s[i]-'a');
        if(t){
            for(int i=1;i<=cnt;i++) c[l[i]]++;
            for(int i=n;i>=0;i--) c[i]+=c[i+1];
            for(int i=1;i<=cnt;i++) a[c[l[i]]--]=i;
            
            for(int i=1;i<=cnt;i++){
                int now=a[i];
                siz[f[now]]+=siz[now];
            }
        }
        else{
            fill(siz+1,siz+cnt+1,1);
        }
    }
    
    void dfs1(int x){
        tot[x]=siz[x];
        for(int i=0;i<26;i++) if(ch[x][i]){
            if(!tot[ch[x][i]]) dfs1(ch[x][i]);
            tot[x]+=tot[ch[x][i]];
        }
    }
    
    void dfs2(int x){
        if(k<=siz[x]){
            k=0,puts("");
            return;
        }
        
        k-=siz[x];
        
        for(int i=0;i<26;i++) if(ch[x][i]){
            if(k>tot[ch[x][i]]) k-=tot[ch[x][i]];
            else putchar('a'+i),dfs2(ch[x][i]);
            
            if(!k) return;
        }
    }
    
    inline void solve(){
        siz[1]=0;
        dfs1(1);
        if(k>tot[1]) puts("-1");
        else dfs2(1);
    }
    
    int main(){
        scanf("%s",s),n=strlen(s);
        scanf("%d%d",&t,&k);
        build();
        solve();
        return 0;
    }
    

      

  • 相关阅读:
    python day04 列表增删改查
    python day03 字符串操作
    python day02 格式化输出逻辑运算
    面试题
    python基础练习题(一)
    编译安装PostgreSQL
    Python函数初识二
    Python函数初识
    笨办法学Python
    笨办法学Python
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8466124.html
Copyright © 2011-2022 走看看