1. 程式人生 > >【LG1368】工藝

【LG1368】工藝

etc spa ++ void %d gin lin problem clas

【LG1368】工藝

題面

洛谷

題解

好套路的一道題。。。

我們倍長這個字符串,然後我們要查詢的串就為這個倍長過後串的長度\(n\)一個子串,要求字典序最小

然後就可以非常愉快地後綴排序了

後綴的話,直接往每個狀態的字典序最小的後繼狀態跑就行了。

代碼

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring> 
#include <cmath> 
#include <algorithm>
#include <map> 
using namespace std; 
inline int gi() {
    register int data = 0, w = 1;
    register char ch = 0;
    while (!isdigit(ch) && ch != '-') ch = getchar(); 
    if (ch == '-') w = -1, ch = getchar(); 
    while (isdigit(ch)) data = 10 * data + ch - '0', ch = getchar(); 
    return w * data; 
} 
const int MAX_N = 3e5 + 5; 
struct Node { 
    map<int, int> ch; 
    int len, fa; 
} t[MAX_N << 2];
int tot = 1, lst = 1; 
void extend(int c) { 
    ++tot, t[lst].ch[c] = tot; 
    t[tot].len = t[lst].len + 1; 
    int p = t[lst].fa; lst = tot;
    while (p && t[p].ch.find(c) == t[p].ch.end()) t[p].ch[c] = tot, p = t[p].fa; 
    if (!p) t[tot].fa = 1; 
    else { 
        int q = t[p].ch[c]; 
        if (t[q].len == t[p].len + 1) t[tot].fa = q; 
        else { 
            int _q = ++tot; t[_q] = t[q]; 
            t[tot - 1].fa = t[q].fa = _q, t[_q].len = t[p].len + 1; 
            while (p) { 
                map<int, int> :: iterator ite;
                ite = t[p].ch.find(c); 
                if (ite == t[p].ch.end() || ite->second != q) break; 
                t[p].ch[c] = _q;
                p = t[p].fa; 
            } 
        } 
    } 
}
int N, a[MAX_N]; 
int main () {
#ifndef ONLINE_JUDGE 
    freopen("cpp.in", "r", stdin);
    freopen("cpp.out", "w", stdout);
#endif 
    N = gi();
    for (int i = 1; i <= N; i++) a[i] = gi(); 
    for (int i = 1; i <= N; i++) extend(a[i]);
    for (int i = 1; i <= N; i++) extend(a[i]); 
    int v = 1; 
    for (int i = 1; i <= N; i++) { 
        printf("%d ", t[v].ch.begin()->first); 
        v = t[v].ch.begin()->second; 
    }
    putchar('\n'); 
    return 0; 
} 

【LG1368】工藝