forked from ShahjalalShohag/code-library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Palindromic Tree Persistent.cpp
109 lines (107 loc) · 2.74 KB
/
Palindromic Tree Persistent.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6 + 9;
// cnt contains the number of palindromic suffixes of the node
// t[cur].smart_link[c] -> link to the maximum length of a palindromic suffix of t[cur]
// s.t. ch is the immediate previous char of that suffix
struct PalindromicTree {
static const int A = 2;
struct node {
int nxt[A], len, st, en, link, cnt, oc, smart_link[A];
node() {
memset(nxt, 0, sizeof nxt);
for (int i = 0; i < A; i++) {
smart_link[i] = 1;
}
}
};
string s; vector<node> t;
vector<array<int, 4>> changes;
int sz, last;
vector<int> pref;
PalindromicTree() {
s = ""; t.resize(3);
sz = 2, last = 2;
t[1].len = -1, t[1].link = 1;
t[2].len = 0, t[2].link = 1;
changes.clear();
}
int extend(char c) {
int cur = last, curlen = 0, pos = s.size();
pref.push_back(0);
if (pos) {
pref[pos] = pref[pos - 1];
}
s += c; int ch = c - 'a';
if (pos - t[cur].len - 1 < 0 || s[pos - t[cur].len - 1] != c) {
cur = t[cur].smart_link[ch];
}
if (t[cur].nxt[ch]) {
changes.push_back({last, t[cur].nxt[ch], -1, -1});
last = t[cur].nxt[ch];
t[last].oc++;
return 0;
}
changes.push_back({last, -1, cur, ch});
sz++; last = sz;
t.emplace_back();
t[sz].oc = 1; t[sz].len = t[cur].len + 2;
pref[pos] = max(pref[pos], t[sz].len);
t[cur].nxt[ch] = sz;
t[sz].en = pos; t[sz].st = pos - t[sz].len + 1;
if (t[sz].len == 1) {
t[sz].link = 2; t[sz].cnt = 1;
t[sz].smart_link[ch] = 2;
return 1;
}
else {
t[sz].link = t[t[cur].smart_link[ch]].nxt[ch];
for (int i = 0; i < A; i++) {
int x = t[sz].link;
if (pos - t[x].len >= 0 && s[pos - t[x].len] - 'a' == i) {
t[sz].smart_link[i] = x;
}
else {
t[sz].smart_link[i] = t[x].smart_link[i];
}
}
}
t[sz].cnt = 1 + t[t[sz].link].cnt;
return 1;
}
void rollback() {
if (s.size() == 0) return;
s.pop_back();
pref.pop_back();
auto x = changes.back();
int prvlast = x[0], oc = x[1], c = x[2], ch = x[3];
changes.pop_back();
last = prvlast;
if (oc == -1) {
t[c].nxt[ch] = 0;
t.pop_back();
sz--;
}
else {
t[oc].oc--;
}
}
}t;
int32_t main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int q; cin >> q;
while (q--) {
int ty; cin >> ty;
if (ty == 1) {
int k; cin >> k;
t.extend(char(k + 'a'));
}
else {
t.rollback();
}
cout << (t.s.empty() ? 0 : t.pref[t.s.size() - 1]) << '\n';
}
return 0;
}
// https://www.codechef.com/problems/BINPALIN