BZOJ 3998 [TJOI2015]弦论 ——后缀自动机

直接构建后缀自动机。

然后

然后只需要再后缀自动机的go树上类似二分的方法进行查找即可,实际上是“26分”。

然后遇到了处理right集合的问题,然后觉得在go和parent树上上传都是可以的,毕竟一个是向后添加(go),而另一个是向前添加(parent),然后计算出来之后就类似平衡树的查找方式进行查找即可。

然后就A掉了

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
 
#define F(i,j,k) for (int i=j;i<=k;++i)
#define D(i,j,k) for (int i=j;i>=k;--i)
#define maxn 1000005
 
struct SuffixAuto{
    char s[maxn];
    int last,cnt,t,k,len,v[maxn],q[maxn],rit[maxn];
    int l[maxn],go[maxn][26],fa[maxn],sum[maxn];
    void init()
    {
        memset(go,0,sizeof go);
        last=cnt=1;
    }
    void add(int x)
    {
        int p=last,np=last=++cnt; l[np]=l[p]+1; rit[np]=1;
        for (;p&&!go[p][x];p=fa[p]) go[p][x]=np;
        if (!p) fa[np]=1;
        else
        {
            int q=go[p][x];
            if (l[q]==l[p]+1) fa[np]=q;
            else
            {
                int nq=++cnt;
                l[nq]=l[p]+1;
                memcpy(go[nq],go[q],sizeof go[q]);
                fa[nq]=fa[q];
                fa[q]=fa[np]=nq;
                for (;p&&go[p][x]==q;p=fa[p]) go[p][x]=nq;
            }
        }
    }
    void build()
    {
        scanf("%s",s+1); len=strlen(s+1);
        F(i,1,len) add(s[i]-'a');
        scanf("%d%d",&t,&k);
        F(i,1,cnt) v[l[i]]++;
        F(i,1,len) v[i]+=v[i-1];
        D(i,cnt,1) q[v[l[i]]--]=i;
        D(i,cnt,1)
        {
            int tmp=q[i];
            if (t) rit[fa[tmp]]+=rit[tmp];
            else rit[tmp]=1;
        }
        rit[1]=0;
        D(i,cnt,1)
        {
            int tmp=q[i];
            sum[tmp]=rit[tmp];
            F(j,0,25) sum[tmp]+=sum[go[tmp][j]];
        }
    }
    void dfs(int o,int x)
    {
        if (x<=rit[o]) return ;
        x-=rit[o];
        F(i,0,25)
        if (go[o][i]){
            if (x>sum[go[o][i]]) x-=sum[go[o][i]];
            else
            {
                printf("%c",'a'+i);
                dfs(go[o][i],x);
                return;
            }
        }
    }
    void solve()
    {
        if (k>sum[1]) printf("-1\n");
        else dfs(1,k);
    }
}sam;
 
int main()
{
    sam.init();
    sam.build();
    sam.solve();
}

  

 

posted @ 2017-03-01 22:49  SfailSth  阅读(187)  评论(4编辑  收藏  举报