結果

問題 No.465 PPPPPPPPPPPPPPPPAPPPPPPPP
ユーザー しらっ亭しらっ亭
提出日時 2016-12-12 05:46:30
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 184 ms / 2,000 ms
コード長 2,938 bytes
コンパイル時間 2,330 ms
コンパイル使用メモリ 184,984 KB
実行使用メモリ 15,604 KB
最終ジャッジ日時 2024-05-07 13:57:53
合計ジャッジ時間 4,459 ms
ジャッジサーバーID
(参考情報)
judge1 / judge5
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 AC 2 ms
6,940 KB
testcase_02 AC 2 ms
6,944 KB
testcase_03 AC 2 ms
6,940 KB
testcase_04 AC 2 ms
6,940 KB
testcase_05 AC 11 ms
6,944 KB
testcase_06 AC 47 ms
15,476 KB
testcase_07 AC 16 ms
5,760 KB
testcase_08 AC 67 ms
14,956 KB
testcase_09 AC 96 ms
15,076 KB
testcase_10 AC 96 ms
15,204 KB
testcase_11 AC 184 ms
15,080 KB
testcase_12 AC 138 ms
12,008 KB
testcase_13 AC 89 ms
9,828 KB
testcase_14 AC 148 ms
15,524 KB
testcase_15 AC 75 ms
15,336 KB
testcase_16 AC 84 ms
15,076 KB
testcase_17 AC 87 ms
15,172 KB
testcase_18 AC 79 ms
15,460 KB
testcase_19 AC 86 ms
15,604 KB
testcase_20 AC 76 ms
15,404 KB
testcase_21 AC 113 ms
15,468 KB
32_ratsliveonnoevilstar.txt AC 74 ms
15,460 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

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

struct Manacher {
  vector<int> rads;

  // O(|s|)
  Manacher(const string &s) : rads(s.size() * 2 - 1){
    int size = (int) rads.size();
    int i = 0, j = 0;
    while (i < size) {
      while (i - j >= 0 && i + j < size && get(s, i - j) == get(s, i + j)) {
        ++j;
      }
      rads[i] = j;
      int k = 1;
      while (i - k >= 0 && i + k < size && k + rads[i - k] < j) {
        rads[i + k] = rads[i - k], ++k;
      }
      i += k;
      j -= k;
    }
  }

  // s[l, r] is palindrome?
  // O(1)
  bool is_palindrome(int l, int r) {
    assert(l >= 0);
    assert(r >= l);
    assert(r * 2 <= (int) rads.size());

    return rads[l + r] >= r - l + 1;
  }

  private:
  static char get(const string &s, int i) {
    if (i & 1) return '^';
    else return s[i >> 1];
  }
};

int main() {
  cin.tie(nullptr);
  ios::sync_with_stdio(false);

  string s;
  cin >> s;

  int n = s.size();

  assert(n >= 4 && n <= 500000);
  for (char c : s) assert(c >= 'a' && c <= 'z');

  Manacher mana(s);

  vector<int> pl(n);
  vector<int> gpl(n + 1);
  vector<tuple<int, int, int>> G;

  for (int j = 1; j <= n; j++) {

    // G -> G'
    vector<tuple<int, int, int>> H;
    for (const tuple<int, int, int> &idk : G) {
      int i, d, k;
      tie(i, d, k) = idk;
      if (i > 1 && s[i - 2] == s[j - 1]) {
        H.emplace_back(i - 1, d, k);
      }
    }

    // G' -> G''
    deque<tuple<int, int, int>> I;
    int r = -j;
    for (const tuple<int, int, int> &idk : H) {
      int i, d, k;
      tie(i, d, k) = idk;
      if (i - r != d) {
        I.emplace_back(i, i - r, 1);
        if (k > 1) {
          I.emplace_back(i + d, d, k - 1);
        }
      }
      else {
        I.emplace_back(idk);
      }
      r = i + (k - 1) * d;
    }

    if (j > 1 && s[j - 2] == s[j - 1]) {
      I.emplace_back(j - 1, j - 1 - r, 1);
      r = j;
    }
    I.emplace_back(j, j - r, 1);

    G.clear();

    // G'' -> next G
    int ip, dp, kp;
    tie(ip, dp, kp) = I.front(); I.pop_front();
    for (const tuple<int, int, int> &idk : I) {
      int i, d, k;
      tie(i, d, k) = idk;
      if (dp == d) {
        kp += k;
      }
      else {
        G.emplace_back(ip, dp, kp);
        ip = i;
        dp = d;
        kp = k;
      }
    }
    G.emplace_back(ip, dp, kp);

    // calc pl
    for (const tuple<int, int, int> &idk : G) {
      int i, d, k;
      tie(i, d, k) = idk;
      r = i + (k - 1) * d;
      int m = 0;
      if (r - 2 >= 0) m += mana.is_palindrome(0, r - 2);
      if (k > 1 && i - d >= 0) {
        m += gpl[i - d];
      }
      if (d <= i) {
        gpl[i - d] = m;
      }
      pl[j - 1] += m;
    }
  }

  vector<long long> sum_p2(n + 1);
  for (int i = 1; i < n; i++) sum_p2[i + 1] = sum_p2[i] + pl[i];

  long long ans = 0;
  for (int k = 0; k < n - 1; k++) {
    if (mana.is_palindrome(k + 1, n - 1)) {
      ans += sum_p2[k];
    }
  }

  cout << ans << endl;
}
0