#include // #include using namespace std; #if __cplusplus >= 202002L using namespace numbers; #endif template struct y_combinator_result{ F f; template explicit y_combinator_result(T &&f): f(forward(f)){ } template decltype(auto) operator()(Args &&...args){ return f(ref(*this), forward(args)...); } }; template decltype(auto) y_combinator(F &&f){ return y_combinator_result>(forward(f)); } // Each node represents a unique palindromic substring plus 0 and 1 node representing empty even and odd string // Adjacency_Type: array or map where X is the size of the alphabet template struct palindrome_automaton{ // Begin States // len: length of the palindrome // link: suffix link // serial_link[u]: longest proper suffix v with len[u] - len[link[u]] != len[v] - len[link[v]] // depth: # of suffix links till root // occurence: # of occurences of the palindrome as a longest proper palindromic suffix of a prefix vector len{0, -1}, link{1, 0}, serial_link{0, 0}, depth{0, 0}, occurence{1, 0}; vector next = vector(2); // End States vector s{-1}; vector last{0}; long long palindromic_substring_count = 0; int new_state(int l, int u){ len.push_back(l); link.push_back(u); serial_link.push_back(l - len[u] == len[u] - len[link[u]] ? serial_link[u] : u); depth.push_back(depth[u] + 1); next.emplace_back(); occurence.push_back(0); return (int)len.size() - 1; } void extend(const vector &s){ for(auto c: s) extend(c); } void extend(Char_Type c){ s.push_back(c); int l = last.back(); while(s[(int)s.size() - len[l] - 2] != s.back()) l = link[l]; if(!next[l][c]){ int u = link[l]; while(s[(int)s.size() - len[u] - 2] != s.back()) u = link[u]; int v = new_state(len[l] + 2, next[u][c]); next[l][c] = v; // Separated for UB in C++14 or below } last.push_back(next[l][c]); palindromic_substring_count += depth[last.back()]; ++ occurence[last.back()]; } int size() const{ // # of states return (int)len.size(); } // count: # of occurences of the palindrome vector count; vector> inv_link; void init_count(){ count = occurence, inv_link.assign(size(), {}); for(auto u = 2; u < (int)size(); ++ u) inv_link[link[u]].push_back(u); auto dfs = [&](auto self, int u)->void{ for(auto v: inv_link[u]) self(self, v), count[u] += count[v]; }; dfs(dfs, 0); } }; int main(){ cin.tie(0)->sync_with_stdio(0); cin.exceptions(ios::badbit | ios::failbit); vector s; { string t; cin >> t; for(auto c: t){ s.push_back(c - 'a'); } } const int mx = 26; palindrome_automaton> aut; aut.extend(s); aut.init_count(); vector res(aut.size()); for(auto s = 0; s < 2; ++ s){ y_combinator([&](auto self, int u)->void{ res[u] += 1LL * aut.count[u] * max(0, aut.len[u]); for(auto v: aut.inv_link[u]){ if(v <= 1){ continue; } res[v] += res[u]; self(v); } })(s); } cout << ranges::max(res) << "\n"; return 0; } /* */