Submission #807566

#TimeUsernameProblemLanguageResultExecution timeMemory
807566peijar회문 (APIO14_palindrome)C++17
100 / 100
53 ms65288 KiB
#include <bits/stdc++.h>
using namespace std;

string to_string(string s) { return s; }
template <typename T> string to_string(T v) {
  bool first = true;
  string res = "[";
  for (const auto &x : v) {
    if (!first)
      res += ", ";
    first = false;
    res += to_string(x);
  }
  res += "]";
  return res;
}

void dbg_out() { cout << endl; }
template <typename Head, typename... Tail> void dbg_out(Head H, Tail... T) {
  cout << ' ' << to_string(H);
  dbg_out(T...);
}

#ifdef DEBUG
#define dbg(...) cout << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)
#else
#define dbg(...)
#endif

const int MAX_TRA = 26; // number of transitions
int normalize(char c) { // normalize `c` in [0, ..., MAX_TRA-1]
  return c - 'a';
}

struct PalindromicTree {
  // len = length of the palindrome, sufCount = number of suffix palindrome
  // link = node of the maximum suffix palindrome, occAsMax = used in computeOcc
  struct Node {
    int len, link, sufCount, occAsMax, occ;
    array<int, MAX_TRA> next;
    Node() : occAsMax(0), occ(0) { next.fill(-1); }
  };

  string s;
  vector<Node> t; // tree. node 0: root with len -1, node 1: root with len 0
  int suff;       // node of the current maximum suffix palindrome

  PalindromicTree() {
    suff = 1;
    t.resize(2);
    t[0].len = -1;
    t[0].link = 0;
    t[0].sufCount = 0;
    t[1].len = 0;
    t[1].link = 0;
    t[1].sufCount = 0;
  }

  int suffix(int x, int i) {
    while (i - t[x].len - 1 < 0 || s[i - t[x].len - 1] != s[i])
      x = t[x].link;
    return x;
  }

  // returns true if `c` created a new distinct palindrome
  bool add(char c) {
    int let = normalize(c);
    int pos = s.size();
    s.push_back(c);
    suff = suffix(suff, pos);

    bool newNode = t[suff].next[let] == -1;
    if (newNode) {
      int x = t.size();
      t[suff].next[let] = x;
      dbg(x);
      t.emplace_back();
      t[x].len = t[suff].len + 2;
      t[x].link = suff == 0 ? 1 : t[suffix(t[suff].link, pos)].next[let];
      t[x].sufCount = 1 + t[t[x].link].sufCount;
    }
    int x = t[suff].next[let];
    ++t[x].occAsMax;
    suff = x;
    return newNode;
  }

  void getOcc() {
    for (int i = (int)t.size() - 1; i >= 0; --i) {
      t[i].occ += t[i].occAsMax;
      t[t[i].link].occ += t[i].occ;
    }
    t[0].occ = t[1].occ = 0;
  }
};

signed main(void) {
  ios_base::sync_with_stdio(false);
  cin.tie(0);

  string s;
  cin >> s;
  PalindromicTree tree;
  for (char c : s)
    tree.add(c);
  tree.getOcc();

  long long sol = 0;
  for (int i = 2; i < (int)tree.t.size(); ++i) {
    int len = tree.t[i].len;
    int occ = tree.t[i].occ;
    dbg(len, occ);
    sol = max(sol, len * 1LL * occ);
  }
  cout << sol << 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...