#include #include #include #include #include using namespace std; // Manacher のアルゴリズム // 各インデックスについて回文半径を線形時間で求める // ダミー文字を挟むことにより偶数長回文にも対応 template struct Manacher { ArrayType v; ElemType dummy; vector rad; ArrayType insert_dummy_elem(ArrayType vec, ElemType dummy) { int N = vec.size(); ArrayType res(2*N - 1, dummy); for(int i=0; i(N); for(i=j=0; i= 0 and i+j < N and v[i-j] == v[i+j]) j++; rad[i] = j; int k; for(k=1; i-k >= 0 and rad[i]-k > rad[i-k]; k++) rad[i+k] = rad[i-k]; i += k; j = max(0, j-k); } } Manacher(ArrayType v_, ElemType dummy_) : v(v_), dummy(dummy_) { v = insert_dummy_elem(v, dummy); build(); } // idx を中心とする回文半径 (0-indexed) int get_rad(int idx) { return (rad[2*idx] + 1) / 2; } // 部分文字列 [l, r) が回文かどうか (0-indexed) bool is_palindrome(int l, int r) { if(l == r) return true; int idx = l + r - 1, len = r - l; return rad[idx] >= len; } void dump(bool is_string = true) { int N = v.size(); if(is_string) { for(int i=0; i Yes\n", i, j); } } } }; void tiny_test_str() { string s; cin >> s; char dummy = '$'; Manacher man(s, dummy); man.dump(); } void tiny_test_int() { int N; cin >> N; vector v(N); for(int i=0; i> v[i]; int dummy = 0; Manacher< vector, int > man(v, dummy); man.dump(false); } void yuki_464() { string s; cin >> s; int N = s.size(); Manacher man(s, '$'); long long int dp[5010][5] = {}; dp[0][0] = 1; for(int i=0; i