結果
問題 | No.465 PPPPPPPPPPPPPPPPAPPPPPPPP |
ユーザー | anta |
提出日時 | 2016-12-15 22:59:46 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,517 ms / 2,000 ms |
コード長 | 5,145 bytes |
コンパイル時間 | 2,266 ms |
コンパイル使用メモリ | 190,144 KB |
実行使用メモリ | 98,068 KB |
最終ジャッジ日時 | 2024-05-07 15:14:28 |
合計ジャッジ時間 | 18,194 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,944 KB |
testcase_04 | AC | 2 ms
6,944 KB |
testcase_05 | AC | 168 ms
6,940 KB |
testcase_06 | AC | 875 ms
17,324 KB |
testcase_07 | AC | 182 ms
7,120 KB |
testcase_08 | AC | 845 ms
20,580 KB |
testcase_09 | AC | 927 ms
33,704 KB |
testcase_10 | AC | 916 ms
35,888 KB |
testcase_11 | AC | 1,097 ms
98,068 KB |
testcase_12 | AC | 804 ms
80,656 KB |
testcase_13 | AC | 573 ms
45,708 KB |
testcase_14 | AC | 1,016 ms
71,504 KB |
testcase_15 | AC | 947 ms
53,736 KB |
testcase_16 | AC | 921 ms
44,820 KB |
testcase_17 | AC | 924 ms
45,584 KB |
testcase_18 | AC | 931 ms
62,540 KB |
testcase_19 | AC | 870 ms
48,120 KB |
testcase_20 | AC | 897 ms
24,652 KB |
testcase_21 | AC | 1,517 ms
56,076 KB |
32_ratsliveonnoevilstar.txt | AC | 928 ms
55,872 KB |
ソースコード
#include "bits/stdc++.h" using namespace std; #define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i)) #define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i)) #define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i)) static const int INF = 0x3f3f3f3f; static const long long INFL = 0x3f3f3f3f3f3f3f3fLL; typedef vector<int> vi; typedef pair<int, int> pii; typedef vector<pair<int, int> > vpii; typedef long long ll; template<typename T, typename U> static void amin(T &x, U y) { if (y < x) x = y; } template<typename T, typename U> static void amax(T &x, U y) { if (x < y) x = y; } struct PalindromicTree { typedef int Index; typedef char Alpha; struct Node { //回文の長さ Index length; //文字列 A が親の回文で、文字 b に対して bAb が自分の回文のとき、border == b となる。 Alpha border; Index head, next; //最長接尾回文。S[i,j]がこのnodeの回文の時、S[k,j] (i < k) がnode->suffixの回文となる。 Index suffix; Index diff; Index seriesLink, seriesLen; Node() { } Node(Index length_, Alpha border_, Index next_, Index suffix_) : length(length_), border(border_), head(-1), next(next_), suffix(suffix_), diff(0), seriesLink(-1), seriesLen(0) { } }; Index nNodes; vector<Node> nodes; vector<Alpha> alphas; void init(Index n) { assert(n >= 0); nodes.resize(n + 2); nodes[0] = Node(-1, '\0', -1, -1); nodes[1] = Node(0, '\0', -1, 0); nNodes = 2; alphas.resize(n); } Index getOddRoot() const { return 0; } Index getEvenRoot() const { return 1; } Index findChild(Index i, Alpha alpha) const { Index c = nodes[i].head; while (c != -1) { if (nodes[c].border == alpha) return c; c = nodes[c].next; } return -1; } Index findSuffixExtension(Index i, Index pos, Index beginningPos) const { while (1) { Index len = nodes[i].length, left = pos - 1 - len; if (beginningPos <= left && alphas[left] == alphas[pos]) return i; i = nodes[i].suffix; } } bool processAlphabet(Index &activeIndex, Index pos, Index beginningPos) { Alpha alpha = alphas[pos]; Index parentIndex = findSuffixExtension(activeIndex, pos, beginningPos); Index childIndex = findChild(parentIndex, alpha); if (childIndex != -1) { activeIndex = childIndex; return false; } Node &parent = nodes[parentIndex]; Index suffixIndex; if (parent.length == -1) { suffixIndex = getEvenRoot(); } else { Index suffixParentIndex = findSuffixExtension(parent.suffix, pos, beginningPos); suffixIndex = findChild(suffixParentIndex, alpha); } childIndex = nNodes++; nodes[childIndex] = Node(parent.length + 2, alpha, parent.head, suffixIndex); activeIndex = parent.head = childIndex; return true; } }; int main() { char S[500001]; while (~scanf("%s", S)) { int n = (int)strlen(S); PalindromicTree pt; pt.init(n); vector<int> sufNode(n + 1, -1); vector<bool> prePalin(n + 1); prePalin[0] = true; { int activeIndex = pt.getEvenRoot(); rep(i, n) { pt.alphas[i] = S[i]; pt.processAlphabet(activeIndex, i, 0); sufNode[i + 1] = activeIndex; prePalin[i + 1] = pt.nodes[activeIndex].length == i + 1; } } reu(i, 2, pt.nNodes) { auto &node = pt.nodes[i], &link = pt.nodes[node.suffix]; node.diff = node.length - link.length; if (node.diff == link.diff) { node.seriesLink = link.seriesLink; node.seriesLen = link.seriesLen + 1; } else { node.seriesLink = node.suffix; node.seriesLen = 1; } } vector<int> Ls(n + 1); const int Small = 500; vector<vector<pair<int,int>>> queries(Small); rer(i, 2, n) { int cnt = 0; int num = 0; for (int u = sufNode[i]; u >= 2; u = pt.nodes[u].seriesLink) { ++num; int initLen = pt.nodes[u].length, diff = pt.nodes[u].diff, seriesLen = pt.nodes[u].seriesLen; if (diff < Small) { queries[diff].emplace_back(i - initLen, i * 2 + 1); queries[diff].emplace_back(i - initLen + seriesLen * diff, i * 2 + 0); } else { for (int k = 0; k < seriesLen; ++k) cnt += prePalin[i - initLen + k * diff]; } } assert(1 << (num - 1) <= n); if (prePalin[i]) --cnt; Ls[i] = cnt; } { prePalin.resize(n + 1 + Small); int cur[Small]; reu(k, 1, Small) { auto &v = queries[k]; sort(v.begin(), v.end()); rep(t, k) cur[t] = 0; int j = 0, qi = 0; rep(i, n + k + 1) { for (; qi != v.size() && v[qi].first == i; ++qi) { Ls[v[qi].second / 2] += (v[qi].second % 2 ? -1 : 1) * cur[j]; } cur[j] += prePalin[i]; if (++j == k) j = 0; } assert(qi == v.size()); } } vector<bool> sufPalin(n + 1); PalindromicTree revPT; revPT.init(n); sufPalin[n] = true; { int activeIndex = pt.getEvenRoot(); rep(i, n) { revPT.alphas[i] = S[n - 1 - i]; revPT.processAlphabet(activeIndex, i, 0); sufPalin[n - 1 - i] = revPT.nodes[activeIndex].length == i + 1; } } ll ans = 0; { int R = 0; for (int i = n - 2; i >= 2; --i) { int L = Ls[i]; if (sufPalin[i + 1]) ++R; ans += (ll)L * R; } } printf("%lld\n", ans); } return 0; }