結果
問題 | No.263 Common Palindromes Extra |
ユーザー | ei1333333 |
提出日時 | 2022-03-15 02:36:35 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 300 ms / 2,000 ms |
コード長 | 5,150 bytes |
コンパイル時間 | 2,467 ms |
コンパイル使用メモリ | 219,552 KB |
実行使用メモリ | 170,096 KB |
最終ジャッジ日時 | 2024-09-21 15:21:17 |
合計ジャッジ時間 | 4,106 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 12 ms
12,800 KB |
testcase_01 | AC | 6 ms
11,904 KB |
testcase_02 | AC | 7 ms
12,024 KB |
testcase_03 | AC | 16 ms
13,824 KB |
testcase_04 | AC | 45 ms
19,732 KB |
testcase_05 | AC | 67 ms
20,824 KB |
testcase_06 | AC | 11 ms
13,048 KB |
testcase_07 | AC | 107 ms
55,832 KB |
testcase_08 | AC | 123 ms
56,472 KB |
testcase_09 | AC | 169 ms
92,480 KB |
testcase_10 | AC | 300 ms
170,096 KB |
testcase_11 | AC | 40 ms
17,952 KB |
ソースコード
#include<bits/stdc++.h> using namespace std; using int64 = long long; //const int mod = 1e9 + 7; const int mod = 998244353; const int64 infll = (1LL << 62) - 1; const int inf = (1 << 30) - 1; struct IoSetup { IoSetup() { cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(10); cerr << fixed << setprecision(10); } } iosetup; template< typename T1, typename T2 > ostream &operator<<(ostream &os, const pair< T1, T2 > &p) { os << p.first << " " << p.second; return os; } template< typename T1, typename T2 > istream &operator>>(istream &is, pair< T1, T2 > &p) { is >> p.first >> p.second; return is; } template< typename T > ostream &operator<<(ostream &os, const vector< T > &v) { for(int i = 0; i < (int) v.size(); i++) { os << v[i] << (i + 1 != v.size() ? " " : ""); } return os; } template< typename T > istream &operator>>(istream &is, vector< T > &v) { for(T &in: v) is >> in; return is; } template< typename T1, typename T2 > inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); } template< typename T1, typename T2 > inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); } template< typename T = int64 > vector< T > make_v(size_t a) { return vector< T >(a); } template< typename T, typename... Ts > auto make_v(size_t a, Ts... ts) { return vector< decltype(make_v< T >(ts...)) >(a, make_v< T >(ts...)); } template< typename T, typename V > typename enable_if< is_class< T >::value == 0 >::type fill_v(T &t, const V &v) { t = v; } template< typename T, typename V > typename enable_if< is_class< T >::value != 0 >::type fill_v(T &t, const V &v) { for(auto &e: t) fill_v(e, v); } template< typename F > struct FixPoint : F { FixPoint(F &&f) : F(forward< F >(f)) {} template< typename... Args > decltype(auto) operator()(Args &&... args) const { return F::operator()(*this, forward< Args >(args)...); } }; template< typename F > inline decltype(auto) MFP(F &&f) { return FixPoint< F >{forward< F >(f)}; } /** * @brief Palindromic Tree(回文木) * @see https://math314.hateblo.jp/entry/2016/12/19/005919 * @docs docs/palindromic-tree.md */ template< typename T = char > struct PalindromicTree { public: struct Node { map< T, int > link; // 子のidx int suffix_link; // 最長回文接尾辞のidx int len; // 対応する回文の長さ vector< int > idx; // 対応する回文を最長回文接尾辞とするidx Node() = default; Node(int suf, int len) : suffix_link(suf), len(len) {} }; vector< Node > ns; int ptr; vector< T > vs; private: int find_prev_palindrome(int cur) const { int pos = (int) vs.size() - 1; for(;;) { int rev = pos - 1 - ns[cur].len; if(rev >= 0 and vs[rev] == vs.back()) break; cur = ns[cur].suffix_link; } return cur; } bool output_dfs(int v, int id, vector< T > &ret) const { if(v == id) return true; for(auto &nxt: ns[v].link) { if(output_dfs(nxt.second, id, ret)) { ret.emplace_back(nxt.first); return true; } } return false; } public: PalindromicTree() : ptr(0) { ns.emplace_back(0, -1); // 長さ -1 ns.emplace_back(0, 0); // 長さ 0 } PalindromicTree(const string &S) : PalindromicTree() { add(S); } int add(const T &x) { int idx = (int) vs.size(); vs.emplace_back(x); int cur = find_prev_palindrome(ptr); auto res = ns[cur].link.insert(make_pair(x, (int) ns.size())); ptr = res.first->second; if(res.second) { ns.emplace_back(-1, ns[cur].len + 2); ns.back().idx.emplace_back(idx); if(ns.back().len == 1) { ns.back().suffix_link = 1; } else { ns.back().suffix_link = ns[find_prev_palindrome(ns[cur].suffix_link)].link[x]; } return ptr; } else { ns[ptr].idx.emplace_back(idx); return ptr; } } void add(const string &s) { for(auto &x: s) add(x); } vector< int > build_frequency() const { vector< int > ret(ns.size()); for(int i = (int) ns.size() - 1; i > 0; i--) { ret[i] += (int) ns[i].idx.size(); ret[ns[i].suffix_link] += ret[i]; } return ret; } vector< T > output(int idx) const { if(idx == 0) return {-1}; if(idx == 1) return {0}; vector< T > ret; output_dfs(0, idx, ret); output_dfs(1, idx, ret); int start = (int) ret.size() - 1; if(ns[idx].len & 1) --start; for(int i = start; i >= 0; i--) { ret.emplace_back(ret[i]); } return ret; } int size() const { return (int) ns.size(); } Node &operator[](int idx) { return ns[idx]; } }; int main() { string S, T; cin >> S >> T; PalindromicTree t(S + "><" + T); vector< int > dps(1111111), dpt(1111111); for(int i = 0; i < t.size(); i++) { for(auto &j: t[i].idx) { if(j < (int) S.size()) ++dps[i]; else if(j >= (int) S.size() + 2) ++dpt[i]; } } int64 ret = 0; for(int i = t.size() - 1; i > 1; i--) { ret += 1LL * dps[i] * dpt[i]; dps[t[i].suffix_link] += dps[i]; dpt[t[i].suffix_link] += dpt[i]; } cout << ret << "\n"; }