码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj3998: [TJOI2015]弦论

时间:2018-04-01 21:54:26      阅读:162      评论:0      收藏:0      [点我收藏+]

标签:scan   roo   ast   sum   can   while   cstring   get   string   

前几天写的题,今天补写个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]弦论

标签:scan   roo   ast   sum   can   while   cstring   get   string   

原文地址:https://www.cnblogs.com/AKCqhzdy/p/8688264.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!