Submission #403823

#TimeUsernameProblemLanguageResultExecution timeMemory
403823opukittpceno_hhrPalindromes (APIO14_palindrome)C++17
73 / 100
1085 ms43224 KiB
#include <iostream> #include <vector> #include <map> #include <set> #include <queue> #include <algorithm> #include <string> #include <cmath> #include <cstdio> #include <iomanip> #include <fstream> #include <cassert> #include <cstring> #include <unordered_set> #include <unordered_map> #include <numeric> #include <ctime> #include <bitset> #include <complex> #include <chrono> #include <random> #include <functional> using namespace std; typedef long long ll; const int N = 3e5 + 7; const int ALP = 26; namespace Hash { const int MOD = 1e9 + 7; const int BASE = 31; int add(int a, int b) { if (a + b < MOD) { return a + b; } return a + b - MOD; } int sub(int a, int b) { if (a >= b) { return a - b; } return a - b + MOD; } int mul(int a, int b) { return 1LL * a * b % MOD; } int n; int pw[N]; int h[N]; int rh[N]; int req(int i, int j, int len) { i = n - 1 - i; int F = sub(rh[i + len], mul(rh[i], pw[len])); int S = sub(h[j + len], mul(h[j], pw[len])); return F == S; } void init(string s) { n = (int)s.size(); pw[0] = 1; for (int i = 0; i < n; i++) { pw[i + 1] = mul(pw[i], BASE); } for (int i = 0; i < n; i++) { h[i + 1] = add(s[i], mul(h[i], BASE)); } reverse(s.begin(), s.end()); for (int i = 0; i < n; i++) { rh[i + 1] = add(s[i], mul(rh[i], BASE)); } reverse(s.begin(), s.end()); } } namespace SparceTable { const int L = 20; int pw[N]; int mn[L][N]; void init(int n, int *a) { for (int i = 0; i < n; i++) { mn[0][i] = a[i]; } for (int i = 0; i + 1 < L; i++) { for (int j = 0; j + 2 * (1 << i) <= n; j++) { mn[i + 1][j] = min(mn[i][j], mn[i][j + (1 << i)]); } } pw[1] = 0; for (int i = 2; i <= n; i++) { pw[i] = pw[i / 2] + 1; } } int get(int l, int r) { int p = pw[r - l]; return min(mn[p][l], mn[p][r - (1 << p)]); } } namespace SuffixArray { int n; string s; int sa[N]; int wr[N]; int cur_class[N]; tuple<int, int, int> tos[N]; void do_sort() { sort(tos, tos + n); } void build_sa() { s.push_back(0); n++; { vector<char> hv; for (auto c : s) { hv.push_back(c); } sort(hv.begin(), hv.end()); hv.resize(unique(hv.begin(), hv.end()) - hv.begin()); for (int i = 0; i < n; i++) { cur_class[i] = lower_bound(hv.begin(), hv.end(), s[i]) - hv.begin(); } } for (int l = 1; l < n; l *= 2) { for (int i = 0; i < n; i++) { tos[i] = make_tuple(cur_class[i], cur_class[(i + l) % n], i); } do_sort(); int cnt = 0; for (int i = 0; i < n; i++) { cur_class[get<2>(tos[i])] = cnt; if (i + 1 < n) { cnt += (get<0>(tos[i]) != get<0>(tos[i + 1]) || get<1>(tos[i]) != get<1>(tos[i + 1])); } } } n--; for (int i = 0; i < n; i++) { wr[i] = cur_class[i] - 1; } for (int i = 0; i < n; i++) { sa[wr[i]] = i; } } int l[N]; void build_lcp() { for (int i = 0; i < n; i++) { int k = 0; if (i > 0) { k = l[wr[i - 1]]; } k--; k = max(k, 0); int in_l = wr[i]; if (in_l + 1 == n) { l[in_l] = -1; } else { int j = sa[in_l + 1]; while (i + k < n && j + k < n && s[i + k] == s[j + k]) { k++; } l[in_l] = k; } } SparceTable::init(n, l); } int lcp(int i, int j) { if (i == j) { return n - i; } i = wr[i]; j = wr[j]; if (i > j) swap(i, j); return SparceTable::get(i, j); } void init(string s_) { s = s_; n = (int)s.size(); build_sa(); build_lcp(); } } void solve(vector<int> v, int ml, int add, ll &ans) { int n = (int)v.size(); vector<int> l(n); vector<int> r(n); { vector<int> st; for (int i = 0; i < n; i++) { while (!st.empty() && v[st.back()] >= v[i]) { st.pop_back(); } if (st.empty()) { l[i] = -1; } else { l[i] = st.back(); } st.push_back(i); } } { vector<int> st; for (int i = n - 1; i >= 0; i--) { while (!st.empty() && v[st.back()] >= v[i]) { st.pop_back(); } if (st.empty()) { r[i] = n; } else { r[i] = st.back(); } st.push_back(i); } } for (int i = 0; i < n; i++) { ans = max(ans, (ll)(r[i] - l[i]) * (v[i] * ml + add)); } } int cnt[ALP]; signed main() { ios_base::sync_with_stdio(false); cin.tie(0); string s; cin >> s; int n = (int)s.size(); Hash::init(s); SuffixArray::init(s); ll ans = 0; auto cmp = [&](pair<int, int> X, pair<int, int> Y) { int i1, len1, i2, len2; tie(i1, len1) = X; tie(i2, len2) = Y; int sk = SuffixArray::lcp(i1, i2); if (sk >= len1 || sk >= len2) { return len1 < len2; } i1 += sk; i2 += sk; return (i1 == n || s[i1] < s[i2]); }; //single { for (int i = 0; i < n; i++) { cnt[s[i] - 'a']++; ans = max(ans, (ll)cnt[s[i] - 'a']); } } //even { vector<pair<int, int>> ip; for (int i = 0; i < n; i++) { int mx = -1; int l = -1; int r = n +1; while (r - l > 1) { int mid = (r + l) / 2; if (mid <= i && mid + i <= n && Hash::req(i - 1, i, mid)) { l = mid; } else { r = mid; } } mx = l; ans = max(ans, (ll)2 * mx); if (mx != -1) { ip.push_back({i, mx}); } } sort(ip.begin(), ip.end(), cmp); vector<int> val; for (int i = 0; i + 1 < (int)ip.size(); i++) { val.push_back(min({ip[i].second, ip[i + 1].second, SuffixArray::lcp(ip[i].first, ip[i + 1].first)})); } solve(val, 2, 0, ans); } //odd { vector<pair<int, int>> ip; for (int i = 0; i < n; i++) { int mx = -1; int l = -1; int r = n +1; while (r - l > 1) { int mid = (r + l) / 2; if (mid <= i && mid + i + 1 <= n && Hash::req(i - 1, i + 1, mid)) { l = mid; } else { r = mid; } } mx = l; ans = max(ans, (ll)2 * mx + 1); if (mx != -1) { ip.push_back({i, mx + 1}); } } sort(ip.begin(), ip.end(), cmp); vector<int> val; for (int i = 0; i + 1 < (int)ip.size(); i++) { val.push_back(min({ip[i].second, ip[i + 1].second, SuffixArray::lcp(ip[i].first, ip[i + 1].first)})); } solve(val, 2, -1, ans); } cout << ans << endl; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...