Submission #838767

#TimeUsernameProblemLanguageResultExecution timeMemory
838767popovicirobertPalindromes (APIO14_palindrome)C++14
73 / 100
163 ms43840 KiB
#include <bits/stdc++.h> using namespace std; constexpr int MOD1 = (int) 1e9 + 7; constexpr int MOD2 = (int) 1e9 + 9; struct Hash { int val1 = 0, val2 = 0; Hash operator*(int x) const { Hash h; h.val1 = (1LL * val1 * x) % MOD1; h.val2 = (1LL * val2 * x) % MOD2; return h; } Hash operator*(const Hash& rhs) const { Hash h; h.val1 = (1LL * val1 * rhs.val1) % MOD1; h.val2 = (1LL * val2 * rhs.val2) % MOD2; return h; } Hash operator-(const Hash& rhs) const { Hash h; h.val1 = (val1 - rhs.val1 + MOD1); if (h.val1 >= MOD1) h.val1 -= MOD1; h.val2 = (val2 - rhs.val2 + MOD2); if (h.val2 >= MOD2) h.val2 -= MOD2; return h; } Hash operator+(int x) const { Hash h; h.val1 = val1 + x; if (h.val1 >= MOD1) h.val1 -= MOD1; h.val2 = val2 + x; if (h.val2 >= MOD2) h.val2 -= MOD2; return h; } Hash& operator=(int x) { val1 = val2 = x; return *this; } bool operator==(const Hash& rhs) const { return val1 == rhs.val1 && val2 == rhs.val2; } }; namespace std { template<> struct hash<Hash> { size_t operator()(const Hash& h) const noexcept { return h.val1 ^ h.val2; } }; } using ull = Hash; constexpr int BASE = (int) 666019; constexpr int MAXN = (int) 3e5; char s[MAXN + 5]; ull pref_hash[MAXN + 5]; ull power[MAXN + 5]; inline ull Get(int l, int r) { return pref_hash[r] - pref_hash[l - 1] * power[r - l + 1]; } char str[2 * MAXN + 5]; int len[2 * MAXN + 5]; int Build(char* s, int n) { power[0] = 1; for (int i = 1; i <= n; i++) { pref_hash[i] = pref_hash[i - 1] * BASE + (s[i] - 'a' + 1); power[i] = power[i - 1] * BASE; } int size = 0; str[++size] = '*'; for (int i = 1; i <= n; i++) { str[++size] = s[i]; str[++size] = '*'; } return size; } void Manacher(char* str, int size) { int pos = 1; len[1] = 1; for (int i = 2; i <= size; i++) { len[i] = 1; if (pos + len[pos] >= i) { len[i] = min(pos + len[pos] - i, len[2 * pos - i]); } while (i - len[i] >= 1 && i + len[i] <= size && str[i - len[i]] == str[i + len[i]]) { len[i]++; } if (pos + len[pos] < i + len[i]) { pos = i; } } } unordered_map<ull, int> nodeId; vector<vector<int>> g; vector<int> nodeFreq(1); vector<int> nodeLen(1); void BuildGraph(int size) { int ID = 0; for (int i = 1; i <= size; i++) { int l = len[i]; if (i % 2 == l % 2) { l--; } int prevId = 0; while (l > 0) { ull currHash; int mid = i / 2; if (i % 2 == 1) { currHash = Get(mid - l / 2 + 1, mid + l / 2); } else { currHash = Get(mid - l / 2, mid + l / 2); } int& currId = nodeId[currHash]; if (currId == 0) { currId = ++ID; nodeLen.push_back(l); nodeFreq.push_back(0); } if (currId >= (int)g.size()) { g.resize(currId + 1); } if (prevId == 0) { nodeFreq[currId]++; } else { g[prevId].push_back(currId); } if (currId != ID) { break; } prevId = currId; l -= 2; } } } int main() { #ifdef HOME ifstream cin("input.in"); ofstream cout("output.out"); #endif ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> (s + 1); int n = strlen(s + 1); int size = Build(s, n); Manacher(str, size); // for (int i = 1; i <= size; i++) { // cerr << (char)str[i] << " "; // } // cerr << "\n"; // for (int i = 1; i <= size; i++) { // cerr << len[i] << " "; // } // cerr << "\n"; BuildGraph(size); int nodes = (int)g.size() - 1; vector<int> order(nodes); iota(order.begin(), order.end(), 1); sort(order.begin(), order.end(), [](const int& a, const int& b) { return nodeLen[a] > nodeLen[b]; }); long long answer = 0; for (auto node : order) { // cerr << nodeFreq[node] << " " << nodeLen[node] << "\n"; answer = max(answer, 1LL * nodeFreq[node] * nodeLen[node]); for (auto son : g[node]) { nodeFreq[son] += nodeFreq[node]; } } cout << answer; return 0; }
#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...