bzoj3998: [TJOI2015]弦论

Posted AKCqhzdy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj3998: [TJOI2015]弦论相关的知识,希望对你有一定的参考价值。

前几天写的题,今天补写个blog

T的情况get right集合的时候特判一下。

因为SAM就是有序的,所以可以dfs求解。

把parent树构建出来,sum表示当前子树的right和,搜一下就出来了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int len,a[1100000];
struct node
{
    int w[30];
}ch[1100000];int root,last,cnt;
int dep[1100000],parent[1100000];
void add(int k)
{
    int x=a[k];
    int now=++cnt,p=last;
    dep[now]=k;
    
    while(p!=0&&ch[p].w[x]==0)ch[p].w[x]=now,p=parent[p];
    if(p==0)parent[now]=root;
    else
    {
        int pre=ch[p].w[x];
        if(dep[p]+1==dep[pre])parent[now]=pre;
        else
        {
            int npre=++cnt;
            ch[npre]=ch[pre];
            dep[npre]=dep[p]+1;
            parent[npre]=parent[pre];
            
            parent[now]=parent[pre]=npre;
            while(ch[p].w[x]==pre)ch[p].w[x]=npre,p=parent[p];
        }
    }
    last=now;
}
int Rsort[1100000],sa[1100000];
int Right[1100000];
void get_Right(int T)
{
    for(int i=1;i<=cnt;i++)Rsort[dep[i]]++;
    for(int i=1;i<=len;i++)Rsort[i]+=Rsort[i-1];
    for(int i=cnt;i>=1;i--)sa[Rsort[dep[i]]--]=i;
    
    int now=root;
    for(int i=1;i<=len;i++)
    {
        int x=a[i];
        now=ch[now].w[x];
        Right[now]++;
    }
    for(int i=cnt;i>=1;i--)
    {
        if(T==1)
            Right[parent[sa[i]]]+=Right[sa[i]];
        else
            Right[sa[i]]=1;
    }
    Right[root]=0;
}

int T,k;
int sum[1100000];
void dfs(int now)
{
    if(k<=Right[now])return ;
    k-=Right[now];
    for(int x=1;x<=26;x++)
    {
        if(ch[now].w[x]!=0)
        {
            int next=ch[now].w[x];
            if(k>sum[next])k-=sum[next];
            else
            {
                printf("%c",x+a-1);
                dfs(next);
                return ;
            }
        }
    }
}

char ss[1100000];
int main()
{
    scanf("%s",ss+1);len=strlen(ss+1);
    for(int i=1;i<=len;i++)a[i]=ss[i]-a+1;
    
    root=last=cnt=1;
    for(int i=1;i<=len;i++)add(i);
    
    scanf("%d%d",&T,&k);
    get_Right(T);
    
    for(int i=cnt;i>=1;i--)
    {
        int now=sa[i];sum[now]=Right[now];
        for(int x=1;x<=26;x++)
            if(ch[now].w[x]!=0)sum[now]+=sum[ch[now].w[x]];
    }
    if(k>sum[root])printf("-1\n");
    else dfs(root);
    return 0;
}

 

以上是关于bzoj3998: [TJOI2015]弦论的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3998: [TJOI2015]弦论

●BZOJ 3998 [TJOI2015]弦论

Bzoj3998: [TJOI2015]弦论

bzoj3998: [TJOI2015]弦论

BZOJ3998[TJOI2015]弦论 后缀自动机

BZOJ3998 TJOI2015 弦论 后缀自动机