結果
問題 | No.515 典型LCP |
ユーザー | SPARKLE_math |
提出日時 | 2022-05-03 14:22:40 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 4,583 bytes |
コンパイル時間 | 1,069 ms |
コンパイル使用メモリ | 91,892 KB |
実行使用メモリ | 114,056 KB |
最終ジャッジ日時 | 2024-07-02 13:38:34 |
合計ジャッジ時間 | 5,954 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | TLE | - |
testcase_01 | -- | - |
testcase_02 | -- | - |
testcase_03 | -- | - |
testcase_04 | -- | - |
testcase_05 | -- | - |
testcase_06 | -- | - |
testcase_07 | -- | - |
testcase_08 | -- | - |
testcase_09 | -- | - |
testcase_10 | -- | - |
testcase_11 | -- | - |
testcase_12 | -- | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
ソースコード
#line 1 "main.cpp" #include <iostream> #include <vector> #include <algorithm> #include <string> #include <map> #line 4 "/home/kokoro601/compro_library/String/SuffixArray.hpp" #include <numeric> #line 6 "/home/kokoro601/compro_library/String/SuffixArray.hpp" #include <assert.h> #line 3 "/home/kokoro601/compro_library/DataStructure/SparseTable.hpp" template <class T> class SparseTable { public: std::vector<std::vector<T> > tab; std::vector<int> lookup; void build(const std::vector<T> &v) { int b = 0; int n = v.size(); while (1 << b <= n) b++; tab.assign(b, std::vector<T>(1 << b)); for (int i = 0; i < n; i++) tab[0][i] = v[i]; for (int i = 1; i < b; i++) { int pre_len = 1 << (i - 1); int ub = n - (1 << i); for (int j = 0; j <= ub; j++) { tab[i][j] = std::min(tab[i - 1][j], tab[i - 1][j + pre_len]); } } lookup.resize(v.size() + 1); for (int i = 2; i < lookup.size(); i++) lookup[i] = lookup[i >> 1] + 1; } // [l, r) inline T rmq(int l, int r) { // assert(l < r); int b = lookup[r - l]; return std::min(tab[b][l], tab[b][r - (1 << b)]); } }; #line 8 "/home/kokoro601/compro_library/String/SuffixArray.hpp" // this implemantation is based on // https://megalodon.jp/2022-0430-1612-24/https://wk1080id.hatenablog.com:443/entry/2018/12/25/005926 // the construction of suffix array is O(nlogn), where n is the length of the string class SuffixArray { std::vector<int> sort_cyclic_shifts(const std::string &s) { int n = s.size(); std::vector<int> cn(n), pn(n), p(n), c(n), cnt(n); std::iota(p.begin(), p.end(), 0); std::sort(p.begin(), p.end(), [&](int a, int b) { return s[a] == s[b] ? a < b : s[a] < s[b]; }); c[p[0]] = 0; for (int i = 1; i < n; i++) c[p[i]] = (s[p[i]] == s[p[i - 1]]) ? c[p[i - 1]] : i; for (int len = 1; len < n; len <<= 1) { for (int i = 0; i < n; i++) { pn[i] = p[i] - len; if (pn[i] < 0) pn[i] += n; } std::iota(cnt.begin(), cnt.end(), 0); for (int i = 0; i < n; i++) p[cnt[c[pn[i]]]++] = pn[i]; if (2 * len >= n) break; c[p[0]] = 0; for (int i = 1; i < n; i++) { if (c[p[i]] == c[p[i - 1]] && c[(p[i] + len) % n] == c[(p[i - 1] + len) % n]) cn[p[i]] = cn[p[i - 1]]; else cn[p[i]] = i; } std::swap(c, cn); } return p; } void calc_lcp(std::string &s) { int n = sa.size(); int slen = n - 1; rank.resize(n); lcp.resize(n); for (int i = 0; i < n; i++) rank[sa[i]] = i; int h = 0; lcp[0] = 0; for (int i = 0; i < slen; i++) { int j = sa[rank[i] - 1]; if (h > 0) h--; for (; j + h < n && i + h < n; h++) if (s[j + h] != s[i + h]) break; lcp[rank[i] - 1] = h; } st.build(lcp); } public: std::vector<int> sa, lcp, rank; SparseTable<int> st; bool need_lcp; SuffixArray(std::string &s, bool need_lcp = true): need_lcp(need_lcp) { s.push_back('$'); sa = sort_cyclic_shifts(s); s.pop_back(); if (need_lcp) calc_lcp(s); } int get_lcp(int i, int j) { assert(need_lcp && i != j); int rank_i = rank[i]; int rank_j = rank[j]; if (rank_i > rank_j) std::swap(rank_i, rank_j); return st.rmq(rank_i, rank_j); } }; #line 7 "main.cpp" using namespace std; using ll = long long; using Graph = vector<vector<int> >; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); ll n; cin >> n; vector<int> l(n), offset(n + 1); string s = ""; for (int i = 0; i < n; i++) { string si; cin >> si; l[i] = si.size(); offset[i + 1] = offset[i] + l[i]; s += si; } SuffixArray sa(s); int m; ll x, d; cin >> m >> x >> d; ll ans = 0; for (int k = 0; k < m; k++) { ll i = (x / (n - 1)) + 1; ll j = (x % (n - 1)) + 1; if (i > j) swap(i, j); else j = j + 1; ans += min(min(l[i - 1], l[j - 1]), sa.get_lcp(offset[i - 1], offset[j - 1])); x = (x + d) % (n * (n - 1)); } cout << ans << endl; return 0; }