Problem p01409 (C++) — buggy submission, verdict: Memory Limit Exceeded

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ull P = 1000000007ULL;

string s[2];
set<ull> inv;
vector<int> p;
vector<ull> h;
vector<ull> pmod;
map<ull, ull> pre;
map<ull, ull> has[2];
map<ull, vector<ull>> nxt;

ull geth(int k, int d, int r) {
  int lt = d - r + 1;
  int rt = d + r - 1;

  return h[rt + 1] - h[lt] * pmod[rt - lt + 1];
}

void getsubstr(int k, ull v) {
  for (auto t : nxt[v]) {
    getsubstr(k, t);
    has[k][v] += has[k][t];
  }
}

void prework(const int k) {
  /*---< prepare >---*/

  p.clear();
  h.clear();
  pre.clear();
  nxt.clear();

  string str;
  cin >> str;

  s[k] += '$';

  for (auto c : str) {
    s[k] += c;
    s[k] += '#';
  }

  int len = s[k].length();

  p.resize(len + 5);
  h.resize(len + 5);
  pmod.resize(len + 5);

  /*---< manacher >---*/

  int ma = -1, id = -1;
  for (int i = 0; i < len; ++i) {
    if (i <= ma)
      p[i] = min(ma - i + 1, p[2 * id - i]);
    else
      p[i] = 1;

    while (s[k][i - p[i]] == s[k][i + p[i]])
      ++p[i];

    if (ma < i + p[i] - 1)
      ma = i + p[i] - 1, id = i;
  }

  /*-----< hash >-----*/

  for (int i = 0; i < len; ++i)
    h[i + 1] = h[i] * P + s[k][i];

  pmod[0] = 1;
  for (int i = 1; i <= len; ++i)
    pmod[i] = pmod[i - 1] * P;

  /*----< build >----*/

  for (int i = 0; i < len; ++i) {
    int r = p[i];
    ull v = geth(k, i, r);

    bool flag = true;

    while (!has[k].count(v)) {
      has[k][v];

      if (flag)
        ++has[k][v], flag = false;

      if (s[k][i + r - 1] == '#')
        inv.insert(v);

      if (s[k][i - r + 1] == '$')
        inv.insert(v);

      if (--r == 0)
        break;

      ull n = geth(k, i, r);

      pre[v] = n;
      nxt[n].push_back(v);

      v = n;
    }

    if (flag)
      ++has[k][v];
  }

  for (auto it : has[k])
    if (!pre.count(it.first))
      getsubstr(k, it.first);
}

signed main(void) {
  prework(0);
  prework(1);

  ull answer = 0;

  for (auto it : has[0])
    if (!inv.count(it.first))
      answer += it.second * has[1][it.first];

  cout << answer << endl;
}

Error: MLE

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const ull P = 1000000007ULL;

string s[2];
set<ull> inv;
vector<int> p[2];
vector<ull> h[2];
vector<ull> pmod;
map<ull, ull> has[2];
map<ull, ull> pre[2];
map<ull, vector<ull>> nxt[2];

ull geth(int k, int d, int r) {
  int lt = d - r + 1;
  int rt = d + r - 1;

  return h[k][rt + 1] - h[k][lt] * pmod[rt - lt + 1];
}

void getsubstr(int k, ull v) {
  for (auto t : nxt[k][v]) {
    getsubstr(k, t);
    has[k][v] += has[k][t];
  }
}

void prework(const int k) {
  /*---< prepare >---*/

  string str;
  cin >> str;

  s[k] += '$';

  for (auto c : str) {
    s[k] += c;
    s[k] += '#';
  }

  int len = s[k].length();

  p[k].resize(len + 5);
  h[k].resize(len + 5);
  pmod.resize(len + 5);

  /*---< manacher >---*/

  int ma = -1, id = -1;
  for (int i = 0; i < len; ++i) {
    if (i <= ma)
      p[k][i] = min(ma - i + 1, p[k][2 * id - i]);
    else
      p[k][i] = 1;

    while (s[k][i - p[k][i]] == s[k][i + p[k][i]])
      ++p[k][i];

    if (ma < i + p[k][i] - 1)
      ma = i + p[k][i] - 1, id = i;
  }

  /*-----< hash >-----*/

  for (int i = 0; i < len; ++i)
    h[k][i + 1] = h[k][i] * P + s[k][i];

  pmod[0] = 1;
  for (int i = 1; i <= len; ++i)
    pmod[i] = pmod[i - 1] * P;

  /*----< build >----*/

  for (int i = 0; i < len; ++i) {
    int r = p[k][i];
    ull v = geth(k, i, r);

    bool flag = true;

    while (!has[k].count(v)) {
      has[k][v];

      if (flag)
        ++has[k][v], flag = false;

      if (s[k][i + r - 1] == '#')
        inv.insert(v);

      if (s[k][i - r + 1] == '$')
        inv.insert(v);

      if (--r == 0)
        break;

      ull n = geth(k, i, r);

      pre[k][v] = n;
      nxt[k][n].push_back(v);

      v = n;
    }

    if (flag)
      ++has[k][v];
  }

  for (auto it : has[k])
    if (!pre[k].count(it.first))
      getsubstr(k, it.first);
}

signed main(void) {
  prework(0);
  prework(1);

  ull answer = 0;

  for (auto it : has[0])
    if (!inv.count(it.first))
      answer += it.second * has[1][it.first];

  cout << answer << endl;
}