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;
    }
    

      

  • 相关阅读:
    yocto/bitbake 学习资源
    QEMU/KVM学习资源
    ubuntu 中创建和删除用户
    git 重命名本地和远程分支
    Ubuntu 上搭建 FTP 服务器
    gdb 常见用法
    git log 显示与特定文件相关的 commit 信息
    基于 qemu system mode 运行 arm 程序
    基于 qemu user mode 运行 aarch64 程序
    checking in(airport)
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8466124.html
Copyright © 2011-2022 走看看