Skip to content

Commit 32f6d99

Browse files
committed
Add eertree
1 parent f2a2377 commit 32f6d99

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

cp-algo/data_structures/eertree.hpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#ifndef CP_ALGO_DATA_STRUCTURES_EERTREE_HPP
2+
#define CP_ALGO_DATA_STRUCTURES_EERTREE_HPP
3+
#include <forward_list>
4+
#include <functional>
5+
#include <iostream>
6+
#include <vector>
7+
#include <string>
8+
#include "../bump_alloc.hpp"
9+
namespace cp_algo::data_structures {
10+
template<int sigma = 26, char mch = 'a'>
11+
struct eertree {
12+
eertree(size_t q) {
13+
q += 2;
14+
s = std::string(q, -1);
15+
len = par = link = std::vector(q, 0);
16+
to.resize(q);
17+
link[0] = 1;
18+
len[1] = -1;
19+
}
20+
21+
int get_link(int v) const {
22+
while(s[n - 1] != s[n - len[v] - 2]) {
23+
v = link[v];
24+
}
25+
return v;
26+
}
27+
28+
int get(int v, int c) const {
29+
for(int cu: to[v]) {
30+
if(char(cu) == c) {
31+
return cu >> 8;
32+
}
33+
}
34+
return 0;
35+
}
36+
37+
void add_letter(char c) {
38+
c -= 'a';
39+
s[n++] = c;
40+
last = get_link(last);
41+
if(!get(last, c)) {
42+
int u = get(get_link(link[last]), c);
43+
link[sz] = u;
44+
par[sz] = last;
45+
len[sz] = len[last] + 2;
46+
to[last].emplace_front((sz++ << 8) | c);
47+
}
48+
last = get(last, c);
49+
}
50+
int sufpal(auto &&adjust) const {
51+
return adjust(last);
52+
}
53+
int sufpal() const {
54+
return sufpal(std::identity{});
55+
}
56+
void print(auto &&adjust) const {
57+
std::cout << sz - 2 << "\n";
58+
for(int i = 2; i < sz; i++) {
59+
std::cout << adjust(par[i]) << ' ' << adjust(link[i]) << "\n";
60+
}
61+
}
62+
void print() const {
63+
print(std::identity{});
64+
}
65+
private:
66+
std::vector<std::forward_list<int, bump_alloc<int>>> to;
67+
std::vector<int> len, link, par;
68+
std::string s;
69+
int n = 1, sz = 2, last = 0;
70+
};
71+
}
72+
#endif // CP_ALGO_DATA_STRUCTURES_EERTREE_HPP

verify/string/eertree.test.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// @brief Eertree
2+
#define PROBLEM "https://judge.yosupo.jp/problem/eertree"
3+
#pragma GCC optimize("Ofast,unroll-loops")
4+
#pragma GCC target("tune=native")
5+
#include "cp-algo/data_structures/eertree.hpp"
6+
#include <bits/stdc++.h>
7+
8+
using namespace std;
9+
using namespace cp_algo::data_structures;
10+
11+
int yosupo(int v) {
12+
if(v == 1) {
13+
return -1;
14+
} else if(v > 1) {
15+
return v - 1;
16+
} else {
17+
return 0;
18+
}
19+
}
20+
21+
void solve() {
22+
string s;
23+
cin >> s;
24+
eertree me(size(s));
25+
vector<int> lasts;
26+
lasts.reserve(size(s));
27+
for(auto c: s) {
28+
me.add_letter(c);
29+
lasts.push_back(me.sufpal(yosupo));
30+
}
31+
me.print(yosupo);
32+
ranges::copy(lasts, ostream_iterator<int>(cout, " "));
33+
}
34+
35+
signed main() {
36+
//freopen("input.txt", "r", stdin);
37+
ios::sync_with_stdio(0);
38+
cin.tie(0);
39+
int t = 1;
40+
while(t--) {
41+
solve();
42+
}
43+
}

0 commit comments

Comments
 (0)