結果
問題 | No.599 回文かい |
ユーザー | mai |
提出日時 | 2017-11-25 00:15:39 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 7,666 bytes |
コンパイル時間 | 3,578 ms |
コンパイル使用メモリ | 236,000 KB |
実行使用メモリ | 6,820 KB |
最終ジャッジ日時 | 2024-11-27 08:44:19 |
合計ジャッジ時間 | 9,881 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,820 KB |
testcase_01 | AC | 2 ms
6,816 KB |
testcase_02 | AC | 2 ms
6,820 KB |
testcase_03 | AC | 2 ms
6,816 KB |
testcase_04 | AC | 2 ms
6,816 KB |
testcase_05 | AC | 2 ms
6,820 KB |
testcase_06 | AC | 2 ms
6,816 KB |
testcase_07 | AC | 2 ms
6,820 KB |
testcase_08 | RE | - |
testcase_09 | AC | 2 ms
5,248 KB |
testcase_10 | AC | 5 ms
5,248 KB |
testcase_11 | AC | 4 ms
5,248 KB |
testcase_12 | AC | 6 ms
5,248 KB |
testcase_13 | AC | 5 ms
5,248 KB |
testcase_14 | AC | 32 ms
5,248 KB |
testcase_15 | AC | 10 ms
5,248 KB |
testcase_16 | RE | - |
testcase_17 | TLE | - |
testcase_18 | RE | - |
testcase_19 | AC | 2 ms
5,248 KB |
testcase_20 | RE | - |
evil_0.txt | AC | 38 ms
9,216 KB |
コンパイルメッセージ
main.cpp:88:41: warning: use of 'auto' in parameter declaration only available with '-std=c++20' or '-fconcepts' 88 | int b_search_low(int low, int high, auto compare) { | ^~~~ main.cpp: In function 'int rare::b_search_low(int, int, auto:28)': main.cpp:89:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister] 89 | register int l, h, m; | ^ main.cpp:89:25: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister] 89 | register int l, h, m; | ^ main.cpp:89:28: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister] 89 | register int l, h, m; | ^ main.cpp: At global scope: main.cpp:103:42: warning: use of 'auto' in parameter declaration only available with '-std=c++20' or '-fconcepts' 103 | int b_search_high(int low, int high, auto compare) { | ^~~~ main.cpp: In function 'int rare::b_search_high(int, int, auto:29)': main.cpp:104:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister] 104 | register int l, h, m; | ^ main.cpp:104:25: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister] 104 | register int l, h, m; | ^ main.cpp:104:28: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister] 104 | register int l, h, m; | ^ main.cpp: In instantiation of 'int rare::b_search_low(int, int, auto:28) [with auto:28 = SuffixArray::find(const std::string&, int&, int&)::<lambda(auto:30)>]': main.cpp:177:35: required from here main.cpp:89:22: warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister] 89 | register int l, h, m; |
ソースコード
#pragma GCC optimize ("O3") #pragma GCC target ("avx") #include "bits/stdc++.h" // define macro "/D__MAI" using namespace std; typedef long long int ll; #define xprintf(fmt,...) fprintf(stderr,fmt,__VA_ARGS__) #define debugv(v) {printf("L%d %s > ",__LINE__,#v);for(auto e:v){cout<<e<<" ";}cout<<endl;} #define debuga(m,w) {printf("L%d %s > ",__LINE__,#m);for(int x=0;x<(w);x++){cout<<(m)[x]<<" ";}cout<<endl;} #define debugaa(m,h,w) {printf("L%d %s >\n",__LINE__,#m);for(int y=0;y<(h);y++){for(int x=0;x<(w);x++){cout<<(m)[y][x]<<" ";}cout<<endl;}} #define ALL(v) (v).begin(),(v).end() #define repeat(cnt,l) for(auto cnt=0ll;(cnt)<(l);++(cnt)) #define iterate(cnt,b,e) for(auto cnt=(b);(cnt)!=(e);++(cnt)) #define MD 1000000007ll #define PI 3.1415926535897932384626433832795 #define EPS 1e-12 template<typename T1, typename T2> ostream& operator <<(ostream &o, const pair<T1, T2> p) { o << "(" << p.first << ":" << p.second << ")"; return o; } template<typename iterator> inline size_t argmin(iterator begin, iterator end) { return distance(begin, min_element(begin, end)); } template<typename iterator> inline size_t argmax(iterator begin, iterator end) { return distance(begin, max_element(begin, end)); } template<typename T> T& maxset(T& to, const T& val) { return to = max(to, val); } template<typename T> T& minset(T& to, const T& val) { return to = min(to, val); } void bye(string s, int code = 0) { cout << s << endl; exit(0); } mt19937_64 randdev(8901016); inline ll rand_range(ll l, ll h) { return uniform_int_distribution<ll>(l, h)(randdev); } #ifdef __MAI #define getchar_unlocked getchar #define putchar_unlocked putchar #endif #ifdef __VSCC #define getchar_unlocked _getchar_nolock #define putchar_unlocked _putchar_nolock #endif namespace { #define isvisiblechar(c) (0x21<=(c)&&(c)<=0x7E) class MaiScanner { public: template<typename T> void input_integer(T& var) { var = 0; T sign = 1; int cc = getchar_unlocked(); for (; cc<'0' || '9'<cc; cc = getchar_unlocked()) if (cc == '-') sign = -1; for (; '0' <= cc&&cc <= '9'; cc = getchar_unlocked()) var = (var << 3) + (var << 1) + cc - '0'; var = var*sign; } inline int c() { return getchar_unlocked(); } inline MaiScanner& operator>>(int& var) { input_integer<int>(var); return *this; } inline MaiScanner& operator>>(long long& var) { input_integer<long long>(var); return *this; } inline MaiScanner& operator>>(string& var) { int cc = getchar_unlocked(); for (; !isvisiblechar(cc); cc = getchar_unlocked()); for (; isvisiblechar(cc); cc = getchar_unlocked()) var.push_back(cc); return *this; } template<typename IT> void in(IT begin, IT end) { for (auto it = begin; it != end; ++it) *this >> *it; } }; } MaiScanner scanner; namespace std { template<typename T1, typename T2> class hash<pair<T1, T2>> { public: size_t operator()(const pair<T1, T2>& x) const { return hash<T1>()(x.first) ^ hash<T2>()(x.second); } }; } unordered_map<pair<int, int>, int> memo; namespace rare { int b_search_low(int low, int high, auto compare) { register int l, h, m; l = low; h = high; while (l < h) { m = (l + h) / 2; if (0<compare(m)) { l = m + 1; } else { h = m; } } return compare(l) == 0 ? l : -1; } int b_search_high(int low, int high, auto compare) { register int l, h, m; l = low; h = high; while (l < h) { m = (l + h + 1) / 2; if (0 <= compare(m)) { l = m; } else { h = m - 1; } } return compare(l) == 0 ? l : -1; } } struct SuffixArray { const char* data; int size; vector<const char*> sa; SuffixArray() {} SuffixArray(const string &d) { data = d.c_str(); size = d.size(); } // Suffix Array 生成 O(nlogn) void build() { int i; sa.resize(size); for (i = 0; i<size; i++) { sa[i] = data + i; } // sort(ALL(sa), [](const char* l, const char* r) {return 0>strcmp(l, r); }); // (´・ω・`) vector<int> g(size + 1), b(size + 1); vector<int> v(size + 1); repeat(i, size + 1) { v[i] = i, g[i] = data[i]; } b[0] = 0; b[size] = 0; sort(v.begin(), v.end(), [&](int l, int r) {return l == r ? false : g[l] != g[r] ? g[l] < g[r] : g[l] < g[r]; }); for (int h = 1; b[size] != size; h *= 2) { sort(v.begin(), v.end(), [&](int l, int r) {return l == r ? false : g[l] != g[r] ? g[l] < g[r] : g[l + h] < g[r + h]; }); repeat(i, size) b[i + 1] = b[i] + [&](int l, int r) {return l == r ? false : g[l] != g[r] ? g[l] < g[r] : g[l + h] < g[r + h]; }(v[i], v[i + 1]); repeat(i, size + 1) g[v[i]] = b[i]; } repeat(i, size) { sa[i] = data + v[i]; } return; } void build(const string &d) { data = d.c_str(); size = d.size(); build(); } // find keyword // out_low <= out_highの範囲にkeyword文字列が存在する.out_high-out_low+1個見つかった,とも解釈できる. // foundToIdx(out_low..out_high)とすることで,見つかった文字列の先頭インデックスを得る. // O(mlogn) void find(const string &keyword, int &out_low, int &out_high) { int low, high, l, h, i; auto length = keyword.size(); const char* c_keyword = keyword.c_str(); low = 0; high = sa.size(); for (i = 0; i < length; i++) { l = rare::b_search_low(low, high, [&](auto p) {return *(c_keyword + i) - *(sa[p] + i); }); h = rare::b_search_high(low, high, [&](auto p) {return *(c_keyword + i) - *(sa[p] + i); }); if (l == -1 || h == -1 || h<l) { out_low = -1; out_high = -2; return; } low = l; high = h; } out_low = low; out_high = high; return; } int foundToIdx(int found) { return sa[found] - data; } }; ll m, n, kei; string str; SuffixArray sa; vector<int> revsa; inline bool my_same(int left, int right, int k) { for (int l = 0; l < k; ++l) { if (str[left + l] != str[right - k + l]) return false; } return true; } ll dfs(int left, int right) { //cout << make_pair(left,right) << endl; if (right - left <= 1) return 1; if (memo.count(make_pair(right, left))) return memo[make_pair(right, left)]; // + [left,right]を1つのブロック // + [left,left+k],[right-k,right] で1つのpair ll ans = 1; // (´・ω・`) for (int k = 1; left + k <= right - k; ++k) { //cout << " " << make_pair(left + k, right - k) << endl; if (my_same(left, right, k)) ans = (ans + dfs(left + k, right - k)) % MD; } //cout << make_pair(left,right)<<ans << endl; return memo[make_pair(right, left)] = ans; } int main() { scanner >> str; n = str.size(); sa.build(str); { revsa.resize(n); repeat(i, n) { revsa[(sa.sa[i] - sa.data)] = i; } } ll ans = dfs(0, n); cout << ans << endl; return 0; }