工艺(SAM)

传送门

用SAM可以非常轻松的解决问题。

只要把原串向SAM中插入两次,之后直接从\(t_0\)状态开始每次贪心跑最小就可以了。

因为这个题要用map,所以之前取begin即可。

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define rep(i,a,n) for(register int i = a;i <= n;i++)
#define per(i,n,a) for(register int i = n;i >= a;i--)
#define enter putchar('\n')
#define pr pair<int,int>
#define mp make_pair
#define fi first
#define sc second
using namespace std;
typedef long long ll;
const int M = 600005;
const int N = 10000005;

int read()
{
    int ans = 0,op = 1;char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
    while(ch >='0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
    return ans * op;
}

int n,a[M],b[M];

struct SuffixAutomaton
{
    int last,cnt,l[M<<1],fa[M<<1];
    map<int,int> ch[M<<1];
    void extend(int c)
    {
        int p = last,np = ++cnt;
        last = np,l[np] = l[p] + 1;
        while(p && !ch[p].count(c)) ch[p][c] = np,p = fa[p];
        if(!p) fa[np] = 1;
        else
        {
            int q = ch[p][c];
            if(l[p] + 1 == l[q]) fa[np] = q;
            else
            {
                int nq = ++cnt;
                l[nq] = l[p] + 1,ch[nq] = ch[q];
                fa[nq] = fa[q],fa[q] = fa[np] = nq;
                while(ch[p][c] == q) ch[p][c] = nq,p = fa[p];
            }
        }
    }
    void find()
    {
        int cur = 1;
        rep(i,1,n) printf("%d ",ch[cur].begin()->fi),cur = ch[cur].begin()->sc;
    }
}SAM;

int main()
{
    n = read();
    rep(i,1,n) a[i] = read();
    SAM.last = SAM.cnt = 1;
    rep(i,1,n) SAM.extend(a[i]);
    rep(i,1,n) SAM.extend(a[i]);
    SAM.find();
    return 0;
}

posted @ 2019-01-12 21:05  CaptainLi  阅读(287)  评论(0编辑  收藏  举报