結果
| 問題 |
No.1018 suffixsuffixsuffix
|
| ユーザー |
noshi91
|
| 提出日時 | 2020-04-03 22:26:14 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 97 ms / 2,000 ms |
| コード長 | 7,033 bytes |
| コンパイル時間 | 1,392 ms |
| コンパイル使用メモリ | 90,836 KB |
| 最終ジャッジ日時 | 2025-01-09 13:12:50 |
|
ジャッジサーバーID (参考情報) |
judge2 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 34 |
ソースコード
//#define NDEBUG
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <utility>
#include <vector>
namespace n91 {
using i8 = std::int_fast8_t;
using i32 = std::int_fast32_t;
using i64 = std::int_fast64_t;
using u8 = std::uint_fast8_t;
using u32 = std::uint_fast32_t;
using u64 = std::uint_fast64_t;
using isize = std::ptrdiff_t;
using usize = std::size_t;
struct rep {
struct itr {
usize i;
constexpr itr(const usize i) noexcept : i(i) {}
void operator++() noexcept { ++i; }
constexpr usize operator*() const noexcept { return i; }
constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
};
const itr f, l;
constexpr rep(const usize f, const usize l) noexcept
: f(std::min(f, l)), l(l) {}
constexpr auto begin() const noexcept { return f; }
constexpr auto end() const noexcept { return l; }
};
struct revrep {
struct itr {
usize i;
constexpr itr(const usize i) noexcept : i(i) {}
void operator++() noexcept { --i; }
constexpr usize operator*() const noexcept { return i; }
constexpr bool operator!=(const itr x) const noexcept { return i != x.i; }
};
const itr f, l;
constexpr revrep(const usize f, const usize l) noexcept
: f(l - 1), l(std::min(f, l) - 1) {}
constexpr auto begin() const noexcept { return f; }
constexpr auto end() const noexcept { return l; }
};
template <class T> auto md_vec(const usize n, const T &value) {
return std::vector<T>(n, value);
}
template <class... Args> auto md_vec(const usize n, Args... args) {
return std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
}
template <class T> constexpr T difference(const T &a, const T &b) noexcept {
return a < b ? b - a : a - b;
}
template <class T> void chmin(T &a, const T &b) noexcept {
if (b < a)
a = b;
}
template <class T> void chmax(T &a, const T &b) noexcept {
if (a < b)
a = b;
}
template <class F> class rec_lambda {
F f;
public:
rec_lambda(F &&f) : f(std::move(f)) {}
template <class... Args> auto operator()(Args &&... args) const {
return f(*this, std::forward<Args>(args)...);
}
};
template <class F> auto make_rec(F &&f) { return rec_lambda<F>(std::move(f)); }
template <class T> T scan() {
T ret;
std::cin >> ret;
return ret;
}
} // namespace n91
#include <string>
namespace luma {
using namespace std;
vector<int> Zalgorithm(string s) {
int n = s.size();
vector<int> Z(n);
Z[0] = n;
int i = 1, j = 0;
while (i < n) {
while (i + j < n && s[j] == s[i + j])
++j;
Z[i] = j;
if (j == 0) {
++i;
continue;
}
int k = 1;
while (i + k < n && Z[k] < j - k)
Z[i + k] = Z[k], ++k;
i += k, j -= k;
}
return Z;
}
template <class _T = string, class U = char, int K = 256> struct SA {
using T = _T;
const int n;
const T &s;
vector<int> rnk;
vector<int> sa;
int operator[](int i) const { return sa[i]; }
SA(const string &s) : n(s.size()), s(s), rnk(n) {
sa_is<T, U>(sa, s + U(0), K); // change if T != string
sa.erase(begin(sa));
for (int i = 0; i < n; i++)
rnk[sa[i]] = i;
}
template <class V = string, class W = char>
void sa_is(vector<int> &sa, const V &s, int k) {
int n = s.size();
vector<int> S(n); // or L
//
S.back() = 1;
for (int i = n - 2; i >= 0; i--) {
if (s[i] < s[i + 1])
S[i] = 1;
else if (s[i] > s[i + 1])
S[i] = 0;
else
S[i] = S[i + 1];
}
//
vector<int> lms;
for (int i = 0; i < n; i++)
if (isLMS(S, i))
lms.emplace_back(i);
auto seed = lms;
vector<int> _sa;
inducedSort<V, W>(_sa, s, k, S, seed);
sa.resize(0);
for (auto el : _sa)
if (isLMS(S, el))
sa.emplace_back(el);
vector<int> nums(n, -1);
int num = 0;
nums[sa[0]] = 0;
for (int x = 0; x < (int)sa.size() - 1; x++) {
int i = sa[x], j = sa[x + 1];
int diff = 0;
for (int d = 0; d < n; d++) {
if (s[i + d] != s[j + d] || isLMS(S, i + d) != isLMS(S, j + d)) {
diff = 1;
break;
} else if (d && (isLMS(S, i + d) || isLMS(S, j + d)))
break;
}
if (diff)
num++;
nums[j] = num;
}
auto _nums = nums;
nums.resize(0);
for (int el : _nums)
if (el != -1)
nums.emplace_back(el);
if (num + 1 < (int)nums.size()) {
sa_is<vector<int>, int>(seed, nums, num + 1);
} else {
seed.resize(num + 1);
for (int i = 0; i < num + 1; i++)
seed[nums[i]] = i;
}
for (int &el : seed)
el = lms[el];
inducedSort<V, W>(sa, s, k, S, seed);
}
template <class V = string, class W = char>
void inducedSort(vector<int> &sa, const V &s, int k, const vector<int> &S,
const vector<int> &lms) {
int n = s.size();
sa.resize(n), sa.assign(n, -1);
vector<int> bin(k + 1, 0);
for (W ch : s)
bin[ch + 1]++;
int sum = 0;
for (int &el : bin)
el = sum += el;
// step 1
vector<int> count(k);
for (auto it = rbegin(lms); it != rend(lms); ++it) {
int i = *it;
W ch = s[i];
sa[bin[ch + 1] - 1 - count[ch]] = i;
count[ch]++;
}
// step 2
count.assign(k, 0);
for (int i : sa) {
if (i == -1 || i == 0)
continue;
if (S[i - 1])
continue;
W ch = s[i - 1];
sa[bin[ch] + count[ch]] = i - 1;
count[ch]++;
}
// step 3
count.assign(k, 0);
for (auto it = rbegin(sa); it != rend(sa); ++it) {
int i = *it;
if (i == -1 || i == 0)
continue;
if (!S[i - 1])
continue;
W ch = s[i - 1];
sa[bin[ch + 1] - 1 - count[ch]] = i - 1;
count[ch]++;
}
}
inline bool isLMS(const vector<int> &S, int i) {
return i > 0 && !S[i - 1] && S[i];
}
};
} // namespace luma
namespace n91 {
void main_() {
/*
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
//*/
usize n = scan<usize>();
u64 m = scan<u64>();
const usize q = scan<usize>();
std::string s = scan<std::string>();
std::vector<u64> qs(q);
for (auto &e : qs) {
std::cin >> e;
e -= 1;
}
{
auto z = luma::Zalgorithm(s);
usize i = 1;
while (i != n) {
if (z[i] == n - i) {
break;
}
i += 1;
}
if (n % i == 0) {
m *= n / i;
n = i;
s.resize(i);
}
}
luma::SA<> sa(s + s);
usize qi = 0;
u64 cur = 0;
std::vector<u64> ans(q);
for (const usize i : rep(0, n * 2)) {
if (sa[i] < n) {
while (qi != q && qs[qi] < cur + m - 1) {
ans[qi] = n * (qs[qi] - cur) + n * 2 - sa[i];
qi += 1;
}
cur += m - 1;
} else {
if (qi != q && qs[qi] == cur) {
ans[qi] = n * 2 - sa[i];
qi += 1;
}
cur += 1;
}
}
for (const usize i : rep(0, q)) {
if (i)
std::cout << " ";
std::cout << n * m + 1 - ans[i];
}
std::cout << "\n";
}
} // namespace n91
int main() {
n91::main_();
return 0;
}
noshi91