結果
| 問題 |
No.599 回文かい
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2017-11-25 00:15:39 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
| 結果 |
RE
|
| 実行時間 | - |
| コード長 | 7,666 bytes |
| コンパイル時間 | 14,801 ms |
| コンパイル使用メモリ | 296,808 KB |
| 最終ジャッジ日時 | 2025-01-05 04:23:40 |
|
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 17 RE * 4 TLE * 1 |
コンパイルメッセージ
main.cpp: In function 'int rare::b_search_low(int, int, auto:55)':
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: In function 'int rare::b_search_high(int, int, auto:56)':
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:55) [with auto:55 = SuffixArray::find(const std::string&, int&, int&)::<lambda(auto:57)>]':
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;
| ^
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: In instantiation of 'int rare::b_search_high(int, int, auto:56) [with auto:56 = SuffixArray::find(const std::string&, int&,
ソースコード
#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;
}