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

    [TJOI2015]弦论

    Time Limit: 10 Sec  Memory Limit: 256 MB
    [Submit][Status][Discuss]

    Description

    对于一个给定长度为N的字符串,求它的第K小子串是什么。

    Input

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

    第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个。K的意义如题所述。

    Output

    输出仅一行,为一个数字串,为第K小的子串。如果子串数目不足K个,则输出-1

    Sample Input

    aabc
    0 3

    Sample Output

    aab

    HINT

     N<=5*10^5


    T<2

    K<=10^9
    分析:第K小字符串,可重或者不重;
       对于可重,直接累加后继个数;
       对于不重,每个状态标记为1个即可;
       然后dfs搜索答案即可;
    代码:
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <bitset>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <cassert>
    #include <ctime>
    #define rep(i,m,n) for(i=m;i<=(int)n;i++)
    #define inf 0x3f3f3f3f
    #define mod 1000000007
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define sys system("pause")
    #define ls (rt<<1)
    #define rs (rt<<1|1)
    #define all(x) x.begin(),x.end()
    const int maxn=1e6+10;
    const int N=5e4+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
    int n,m,k,t;
    struct samnode{
        samnode *son[26] , *f;
        int l , now, sc;
    }*root,*last,sam[maxn],*b[maxn];
    int cnt,num[maxn];
    char a[maxn],ret[maxn];
    void init(){
        root = last = &sam[cnt=0];
    }
    void add(int x)
    {
        samnode *p = &sam[++cnt] , *jp=last;
        p->l = jp->l+1;
        last = p;
        for( ; jp&&!jp->son[x] ; jp=jp->f) jp->son[x]=p;
        if(!jp) p->f = root;
        else{
            if(jp->l+1 == jp->son[x]->l) p->f = jp->son[x];
            else{
                samnode *r = &sam[++cnt] , *q = jp->son[x];
                *r = *q;
                r->l = jp->l+1;
                q->f = p->f = r;
                for( ; jp && jp->son[x]==q ; jp=jp->f) jp->son[x]=r;
            }
        }
    }
    int main(){
        int i,j;
        init();
        scanf("%s%d%d",a,&t,&k);
        int len=strlen(a);
        rep(i,0,len-1)add(a[i]-'a');
        samnode *go=root;
        rep(i,0,len-1)go=go->son[a[i]-'a'],go->now=1;
        rep(i,0,cnt)num[sam[i].l]++;
        rep(i,1,len)num[i]+=num[i-1];
        rep(i,0,cnt)b[--num[sam[i].l]]=&sam[i];
        if(!t)rep(i,1,cnt)sam[i].now=1;
        if(t)for(i=cnt;i>=1;i--)b[i]->f->now+=b[i]->now;
        b[0]->sc=b[0]->now=0;
        for(i=cnt;i>=0;i--)
        {
            b[i]->sc=b[i]->now;
            rep(j,0,25)if(b[i]->son[j])b[i]->sc+=b[i]->son[j]->sc;
        }
        if(b[0]->sc<k)
        {
            puts("-1");
            return 0;
        }
        go=root;
        int tot=0;
        while(k>0)
        {
            rep(i,0,25)
            {
                if(go->son[i])
                {
                    if(go->son[i]->sc>=k)
                    {
                        ret[++tot]=i+'a';
                        k-=go->son[i]->now;
                        go=go->son[i];
                        break;
                    }
                    else k-=go->son[i]->sc;
                }
            }
        }
        ret[++tot]=0;
        printf("%s
    ",ret+1);
        return 0;
    }
  • 相关阅读:
    UVA 3942 Remember the Word (Trie+DP)题解
    POJ 3630 Phone List(字符串前缀重复)题解
    HDU 1247 Hat’s Words(字典树)题解
    hdu 1671 Phone List(字典树)题解
    HDU1251 统计难题 (字典树模板)题解
    BZOJ 1556 墓地秘密
    BZOJ 3624 免费道路
    BZOJ 2286 消耗战
    BZOJ 3694 最短路
    BZOJ 1589 采集糖果
  • 原文地址:https://www.cnblogs.com/dyzll/p/7624748.html
Copyright © 2011-2022 走看看