結果
問題 | No.273 回文分解 |
ユーザー | ei1333333 |
提出日時 | 2022-03-16 03:06:12 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 2 ms / 2,000 ms |
コード長 | 6,487 bytes |
コンパイル時間 | 2,449 ms |
コンパイル使用メモリ | 219,268 KB |
実行使用メモリ | 6,944 KB |
最終ジャッジ日時 | 2024-09-22 20:40:30 |
合計ジャッジ時間 | 3,575 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
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,940 KB |
testcase_05 | AC | 2 ms
6,944 KB |
testcase_06 | AC | 2 ms
6,944 KB |
testcase_07 | AC | 2 ms
6,944 KB |
testcase_08 | AC | 2 ms
6,944 KB |
testcase_09 | AC | 2 ms
6,940 KB |
testcase_10 | AC | 2 ms
6,944 KB |
testcase_11 | AC | 2 ms
6,940 KB |
testcase_12 | AC | 2 ms
6,940 KB |
testcase_13 | AC | 2 ms
6,944 KB |
testcase_14 | AC | 2 ms
6,944 KB |
testcase_15 | AC | 2 ms
6,944 KB |
testcase_16 | AC | 2 ms
6,940 KB |
testcase_17 | AC | 2 ms
6,944 KB |
testcase_18 | AC | 2 ms
6,940 KB |
testcase_19 | AC | 2 ms
6,944 KB |
testcase_20 | AC | 2 ms
6,944 KB |
testcase_21 | AC | 2 ms
6,944 KB |
testcase_22 | AC | 2 ms
6,940 KB |
testcase_23 | AC | 2 ms
6,940 KB |
testcase_24 | AC | 2 ms
6,940 KB |
testcase_25 | AC | 2 ms
6,944 KB |
testcase_26 | AC | 2 ms
6,940 KB |
testcase_27 | AC | 2 ms
6,944 KB |
testcase_28 | AC | 2 ms
6,940 KB |
testcase_29 | AC | 2 ms
6,944 KB |
testcase_30 | AC | 2 ms
6,940 KB |
testcase_31 | AC | 2 ms
6,944 KB |
testcase_32 | AC | 2 ms
6,940 KB |
testcase_33 | AC | 2 ms
6,940 KB |
testcase_34 | AC | 2 ms
6,944 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 int delta_link; // 差分が異なる最長回文接尾辞のidx Node() = default; Node(int suf, int len) : suffix_link(suf), len(len), delta_link(-1) {} }; 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 diff(int t) const { if(ns[t].suffix_link <= 0) return -1; return ns[t].len - ns[ns[t].suffix_link].len; } 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); 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]; } if(diff(ptr) == diff(ns.back().suffix_link)) { ns.back().delta_link = ns[ns.back().suffix_link].delta_link; } else { ns.back().delta_link = ns.back().suffix_link; } } ns[ptr].idx.emplace_back(idx); return ptr; } // add(x) のあとに呼び出す // * init(node_idx, pos): 頂点 node_idx を S[pos,i] が回文のときの初期値にする // * apply(node_idx, pre_idx): 頂点 node_idx に 頂点 pre_idx の結果を加える // * update: S[i]を末尾とする回文の頂点番号の集合 template< typename I, typename U > vector< int > update_dp(const I &init, const U &apply) { int i = (int) vs.size() - 1; int id = ptr; vector< int > update; while(ns[id].len > 0) { init(id, i + 1 - ns[ns[id].delta_link].len - diff(id)); if(ns[id].suffix_link != ns[id].delta_link) { apply(id, ns[id].suffix_link); } update.emplace_back(id); id = ns[id].delta_link; } return update; } 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; cin >> S; int N = (int) S.size(); vector< int > dp1(N + 3, -inf), dp2(N + 1, -inf); PalindromicTree t; dp2[0] = 1; for(int i = 0; i < N; i++) { int id = t.add(S[i]); auto ret = t.update_dp([&](int id, int pos) { if(i + 1 - pos == N) dp1[id] = dp2[pos]; else dp1[id] = max(dp2[pos], i + 1 - pos); }, [&](int id, int par) { if(t[id].len == N) chmax(dp1[id], dp1[par]); else chmax(dp1[id], max(dp1[par], t[id].len)); }); for(auto &p: ret) chmax(dp2[i + 1], dp1[p]); } cout << dp2[N] << "\n"; }