Submission #561461

#TimeUsernameProblemLanguageResultExecution timeMemory
561461Ooops_sorryPalindromes (APIO14_palindrome)C++17
73 / 100
1083 ms79732 KiB
#include<bits/stdc++.h> using namespace std; #define pb push_back #define ld long double #define ll long long mt19937 rnd(51); const int INF = 1e9; int MOD1, p1 = 31; ll BIGINF = 1e18; bool is_palindrome(string s) { return s == (string){s.rbegin(), s.rend()}; } ll solve1(string s) { int n = s.size(), ans = -INF; map<string, int> cnt; for (int i = 0; i < n; i++) { for (int j = 1; j + i <= n; j++) { cnt[s.substr(i, j)]++; } } for (int i = 0; i < n; i++) { for (int j = n - i; j >= 1; j--) { if (is_palindrome(s.substr(i, j))) { ans = max(ans, cnt[s.substr(i, j)] * j); } } } return ans; } struct Hash { int MOD, p; vector<int> po, h; Hash(string s, int MOD_, ll p_) { MOD = MOD_, p = p_; int n = s.size(); po.resize(n + 1); h.resize(n + 1); po[0] = 1; for (int i = 1; i <= n; i++) { po[i] = (1ll * po[i - 1] * p) % MOD; } for (int i = 0; i < n; i++) { h[i + 1] = (1ll * h[i] * p + s[i] - 'a' + 1) % MOD; } } int get(int l, int r) { r++; int val = (h[r] - (ll)h[l] * po[r - l]) % MOD; if (val < 0) val += MOD; return val; } }; struct SegTree { vector<int> t; SegTree(int n) { t.resize(4 * n, -1); } void update(int v, int tl, int tr, int l, int r, int val) { if (l > r) return; if (tl == l && tr == r) { t[v] = max(t[v], val); return; } int tm = (tl + tr) / 2; update(2 * v, tl, tm, l, min(r, tm), val), update(2 * v + 1, tm + 1, tr, max(l, tm + 1), r, val); } int get(int v, int l, int r, int pos) { if (l == r) { return t[v]; } int m = (l + r) / 2; if (pos <= m) { return max(t[v], get(2 * v, l, m, pos)); } else { return max(t[v], get(2 * v + 1, m + 1, r, pos)); } } }; vector<int> calc(string val, vector<int> p, vector<int> c) { int n = val.size(); int current_lcp = 0, sum = 0; vector<int> lcp(n); for (int i = 0; i < n; i++) { if (c[i] == n - 1) continue; int nxt = p[c[i] + 1]; while (max(i, nxt) + current_lcp < n && val[i + current_lcp] == val[nxt + current_lcp]) current_lcp++; lcp[c[i]] = current_lcp; current_lcp = max(0, current_lcp - 1); } return lcp; } pair<vector<int>, vector<int>> suffix_array(string s) { s += '#'; int n = s.size(); vector<int> p, c(n); vector<vector<int>> a(n); map<char, vector<int>> all; for (int i = 0; i < n; i++) { all[s[i]].pb(i); } int now = 0; for (auto to : all) { for (auto t : to.second) { c[t] = now; p.pb(t); } now++; } int mx = now, i, k, j; for (i = 0; mx < n; ++i) { int val = (1 << i); for (int j = 0; j < mx; j++) a[j].clear(); for (int j = 0; j < n; j++) { int k = (p[j] - val + n) % n; a[c[k]].pb(k); } auto _c = c; int now = -1, ind = 0; for (k = 0; k < mx; ++k) { for (j = 0; j < a[k].size(); ++j) { if (j == 0 || _c[(a[k][j] + val) % n] != _c[(a[k][j - 1] + val) % n]) now++; c[a[k][j]] = now; p[ind++] = a[k][j]; } } mx = now + 1; } vector<int> ret, rett; s.pop_back(); map<int,int> mpp; for (int i = 1; i < p.size(); i++) ret.pb(p[i]); for (int i = 0; i < ret.size(); i++) mpp[ret[i]] = i; for (auto to : mpp) rett.pb(to.second); return {{p.begin() + 1, p.end()}, calc(s, ret, rett)}; } ll solve2(string s) { int n = s.size(); ll ans = -BIGINF; Hash h1(s, MOD1, p1), h1rev((string){s.rbegin(), s.rend()}, MOD1, p1); SegTree odd(n), even(n); for (int i = 0; i < n; i++) { int l = 0, r = n; while (r - l > 1) { int mid = (r + l) / 2; if (i - mid >= 0 && i + mid < n && h1.get(i - mid, i + mid) == h1rev.get(n - i - mid - 1, n - i + mid - 1)) { l = mid; } else { r = mid; } } odd.update(1, 0, n - 1, i - l, i, i); if (i + 1 < n && s[i] == s[i + 1]) { int l = 0, r = n; while (r - l > 1) { int mid = (r + l) / 2; if (i - mid >= 0 && i + mid + 1 < n && h1.get(i - mid, i + mid + 1) == h1rev.get(n - i - mid - 2, n - i + mid - 1)) { l = mid; } else { r = mid; } } even.update(1, 0, n - 1, i - l, i, i); } } vector<int> pos(n, -1); for (int i = 0; i < n; i++) { int j = odd.get(1, 0, n - 1, i), k = even.get(1, 0, n - 1, i); if (j != -1) { pos[i] = max(pos[i], i + 2 * (j - i)); } if (k != -1) { pos[i] = max(pos[i], i + 1 + 2 * (k - i)); } } vector<int> cnt(n, 1); auto g = suffix_array(s); vector<int> arr = g.first, p = g.second; deque<int> q; for (int i = n - 1; i >= 0; i--) { if (i + 1 < n) { while (q.size() > 0 && p[i] < p[q.back()]) { q.pop_back(); } q.pb(i); } if (pos[arr[i]] != -1) { int len = pos[arr[i]] - arr[i] + 1; if (i + 1 < n && p[q.back()] >= len) { if (p[q[0]] >= len) { cnt[i] += n - i - 1; } else { int l = -1, r = q.size(); while (r - l > 1) { int mid = (r + l) / 2; if (p[q[mid]] >= len) { r = mid; } else { l = mid; } } cnt[i] += q[r - 1] - i; } } } } q.clear(); for (int i = 0; i < n; i++) { if (pos[arr[i]] != -1) { int len = pos[arr[i]] - arr[i] + 1; if (i - 1 >= 0 && p[q.back()] >= len) { if (p[q[0]] >= len) { cnt[i] += i; } else { int l = -1, r = q.size(); while (r - l > 1) { int mid = (r + l) / 2; if (p[q[mid]] >= len) { r = mid; } else { l = mid; } } cnt[i] += i - q[r - 1] - 1; } } ans = max(ans, (ll)cnt[i] * len); } while (q.size() > 0 && p[i] < p[q.back()]) { q.pop_back(); } if (i + 1 < n) { q.pb(i); } } return ans; } bool prime(int v) { for (int i = 2; i * i <= v; i++) { if (v % i == 0) { return 0; } } return 1; } signed main() { #ifdef LOCAL freopen("input.txt", "r", stdin); #endif // LCOAL ios_base::sync_with_stdio(0); cin.tie(0); MOD1 = rnd(); while (MOD1 < (int)(1e9) || !prime(MOD1)) { MOD1 = rnd(); } while (0) { int n = rnd() % 15 + 1; string s = ""; for (int i = 0; i < n; i++) { s += rnd() % 5 + 'a'; } auto res1 = solve1(s), res2 = solve2(s); if (res1 != res2) { cout << s << endl << res1 << ' ' << res2 << endl; return 0; } cout << "ok" << endl; } string s; cin >> s; cout << solve2(s) << endl; return 0; }

Compilation message (stderr)

palindrome.cpp: In function 'std::vector<int> calc(std::string, std::vector<int>, std::vector<int>)':
palindrome.cpp:91:26: warning: unused variable 'sum' [-Wunused-variable]
   91 |     int current_lcp = 0, sum = 0;
      |                          ^~~
palindrome.cpp: In function 'std::pair<std::vector<int>, std::vector<int> > suffix_array(std::string)':
palindrome.cpp:134:27: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  134 |             for (j = 0; j < a[k].size(); ++j) {
      |                         ~~^~~~~~~~~~~~~
palindrome.cpp:146:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  146 |     for (int i = 1; i < p.size(); i++) ret.pb(p[i]);
      |                     ~~^~~~~~~~~~
palindrome.cpp:147:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  147 |     for (int i = 0; i < ret.size(); i++) mpp[ret[i]] = i;
      |                     ~~^~~~~~~~~~~~
#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...