CP-Algorithms Library

This documentation is automatically generated by competitive-verifier/competitive-verifier

View the Project on GitHub cp-algorithms/cp-algorithms-aux

:heavy_check_mark: Eertree (verify/string/eertree.test.cpp)

Depends on

Code

// @brief Eertree
#define PROBLEM "https://judge.yosupo.jp/problem/eertree"
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("tune=native")
#include "cp-algo/data_structures/eertree.hpp"
#include <bits/stdc++.h>

using namespace std;
using namespace cp_algo::data_structures;

int yosupo(int v) {
    if(v == 1) {
        return -1;
    } else if(v > 1) {
        return v - 1;
    } else {
        return 0;
    }
}

void solve() {
    string s;
    cin >> s;
    eertree me(size(s));
    vector<int> lasts;
    lasts.reserve(size(s));
    for(auto c: s) {
        me.add_letter(c);
        lasts.push_back(me.sufpal(yosupo));
    }
    me.print(yosupo);
    ranges::copy(lasts, ostream_iterator<int>(cout, " "));
}

signed main() {
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    while(t--) {
        solve();
    }
}
#line 1 "verify/string/eertree.test.cpp"
// @brief Eertree
#define PROBLEM "https://judge.yosupo.jp/problem/eertree"
#pragma GCC optimize("Ofast,unroll-loops")
#pragma GCC target("tune=native")
#line 1 "cp-algo/data_structures/eertree.hpp"


#include <forward_list>
#include <functional>
#include <iostream>
#include <vector>
#include <string>
#line 1 "cp-algo/bump_alloc.hpp"


#include <cstddef>
namespace cp_algo {
    char buf[450 << 20] alignas(32);
    size_t buf_ind = sizeof buf;
    template<class T> struct bump_alloc {
        typedef T value_type;
        bump_alloc() {}
        template<class U> bump_alloc(const U&) {}
        T* allocate(size_t n) {
            buf_ind -= n * sizeof(T);
            buf_ind &= 0 - alignof(T);
            return (T*)(buf + buf_ind);
        }
        void deallocate(T*, size_t) {}
    };
}

#line 9 "cp-algo/data_structures/eertree.hpp"
namespace cp_algo::data_structures {
    template<int sigma = 26, char mch = 'a'>
    struct eertree {
        eertree(size_t q) {
            q += 2;
            s = std::string(q, -1);
            len = par = link = std::vector(q, 0);
            to.resize(q);
            link[0] = 1;
            len[1] = -1;
        }
        
        int get_link(int v) const {
            while(s[n - 1] != s[n - len[v] - 2]) {
                v = link[v];
            }
            return v;
        }
        
        int get(int v, int c) const {
            for(int cu: to[v]) {
                if(char(cu) == c) {
                    return cu >> 8;
                }
            }
            return 0;
        }
        
        void add_letter(char c) {
            c -= 'a';
            s[n++] = c;
            last = get_link(last);
            if(!get(last, c)) {
                int u = get(get_link(link[last]), c);
                link[sz] = u;
                par[sz] = last;
                len[sz] = len[last] + 2;
                to[last].emplace_front((sz++ << 8) | c);
            }
            last = get(last, c);
        }
        int sufpal(auto &&adjust) const {
            return adjust(last);
        }
        int sufpal() const {
            return sufpal(std::identity{});
        }
        void print(auto &&adjust) const {
            std::cout << sz - 2 << "\n";
            for(int i = 2; i < sz; i++) {
                std::cout << adjust(par[i]) << ' ' << adjust(link[i]) << "\n";
            }
        }
        void print() const {
            print(std::identity{});
        }
    private:
        std::vector<std::forward_list<int, bump_alloc<int>>> to;
        std::vector<int> len, link, par;
        std::string s;
        int n = 1, sz = 2, last = 0;
    };
}

#line 6 "verify/string/eertree.test.cpp"
#include <bits/stdc++.h>

using namespace std;
using namespace cp_algo::data_structures;

int yosupo(int v) {
    if(v == 1) {
        return -1;
    } else if(v > 1) {
        return v - 1;
    } else {
        return 0;
    }
}

void solve() {
    string s;
    cin >> s;
    eertree me(size(s));
    vector<int> lasts;
    lasts.reserve(size(s));
    for(auto c: s) {
        me.add_letter(c);
        lasts.push_back(me.sufpal(yosupo));
    }
    me.print(yosupo);
    ranges::copy(lasts, ostream_iterator<int>(cout, " "));
}

signed main() {
    //freopen("input.txt", "r", stdin);
    ios::sync_with_stdio(0);
    cin.tie(0);
    int t = 1;
    while(t--) {
        solve();
    }
}

Test cases

Env Name Status Elapsed Memory
g++ binary_00 :heavy_check_mark: AC 120 ms 37 MB
g++ binary_01 :heavy_check_mark: AC 136 ms 38 MB
g++ binary_02 :heavy_check_mark: AC 125 ms 37 MB
g++ binary_03 :heavy_check_mark: AC 139 ms 37 MB
g++ example_00 :heavy_check_mark: AC 5 ms 4 MB
g++ example_01 :heavy_check_mark: AC 4 ms 4 MB
g++ example_02 :heavy_check_mark: AC 4 ms 4 MB
g++ random_00 :heavy_check_mark: AC 107 ms 29 MB
g++ random_01 :heavy_check_mark: AC 108 ms 29 MB
g++ random_small_sigma_00 :heavy_check_mark: AC 164 ms 45 MB
g++ random_small_sigma_01 :heavy_check_mark: AC 75 ms 29 MB
g++ random_small_sigma_02 :heavy_check_mark: AC 80 ms 29 MB
g++ random_small_sigma_03 :heavy_check_mark: AC 84 ms 29 MB
g++ random_small_sigma_04 :heavy_check_mark: AC 82 ms 29 MB
g++ short_period_00 :heavy_check_mark: AC 174 ms 44 MB
g++ short_period_01 :heavy_check_mark: AC 109 ms 25 MB
g++ short_period_02 :heavy_check_mark: AC 158 ms 45 MB
g++ short_period_03 :heavy_check_mark: AC 86 ms 26 MB
g++ short_period_04 :heavy_check_mark: AC 189 ms 46 MB
g++ short_period_05 :heavy_check_mark: AC 96 ms 25 MB
g++ short_period_06 :heavy_check_mark: AC 162 ms 45 MB
g++ short_period_07 :heavy_check_mark: AC 98 ms 25 MB
g++ short_period_08 :heavy_check_mark: AC 70 ms 29 MB
g++ short_period_09 :heavy_check_mark: AC 39 ms 16 MB
Back to top page