Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
- #pragma GCC optimize 03
- #pragma GCC optimize("unroll-loops")
- #include <iostream>
- #include <iomanip>
- #include <algorithm>
- #include <iterator>
- #include <cmath>
- #include <ctime>
- #include <vector>
- #include <deque>
- #include <queue>
- #include <set>
- #include <map>
- #include <stack>
- #include <string>
- #include <random>
- #include <numeric>
- #include <unordered_set>
- typedef std::pair<int, int> pii;
- typedef std::pair<char, short> psc;
- typedef std::pair<std::pair<char, short>, std::pair<char, short>> pss;
- typedef unsigned short ushort;
- typedef unsigned long long ull;
- typedef long long ll;
- typedef long double lb;
- #define fast ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
- #define file_in freopen("input.txt", "r", stdin);
- #define file_in_out freopen("swapper.in", "r", stdin); freopen("swapper.out", "w", stdout);
- #define all(x) (x).begin(), (x).end()
- #define fi first
- #define se second
- using namespace std;
- template<typename T>
- istream& operator>>(istream &in, vector<T> &v) {
- for (auto &it : v) {
- in >> it;
- }
- return in;
- }
- template<typename T>
- ostream& operator<<(ostream &out, vector<T> &v) {
- if (!v.empty()) {
- out << v.front();
- for (int i = 1; i < v.size(); ++i) {
- out << " " << v[i];
- }
- }
- return out;
- }
- template<typename T1, typename T2>
- ostream& operator<<(ostream &out, pair<T1, T2> &v) {
- out << v.fi << " " << v.se;
- return out;
- }
- const psc inf = {INT16_MAX, 5};
- psc convert_to_psc(int n) {
- return {n / INT16_MAX, n % INT16_MAX};
- }
- int convert_to_int(psc n) {
- return n.fi * INT16_MAX + n.se;
- }
- bool check_less(psc &p1, psc &p2) {
- return convert_to_int(p1) < convert_to_int(p2);
- }
- psc Min(psc &p1, psc &p2) {
- return (convert_to_int(p1) < convert_to_int(p2) ? p1 : p2);
- }
- psc Max(psc &p1, psc &p2) {
- return (convert_to_int(p1) > convert_to_int(p2) ? p1 : p2);
- }
- ostream& operator<<(ostream &out, psc &v) {
- out << convert_to_int(v);
- return out;
- }
- int bin_search(vector<psc> &v, psc x) {
- int l = -1, r = v.size();
- while (r - l > 1) {
- int m = r + l >> 1;
- if (check_less(v[m], x)) {
- l = m;
- } else {
- r = m;
- }
- }
- return r;
- }
- struct sparse_table {
- vector<vector<pss>> sp;
- sparse_table() {}
- sparse_table(vector<psc> a) {
- int n = a.size();
- int LOG = __lg(n) + 1;
- sp.resize(n, vector<pss>(LOG, {inf, inf}));
- for (int i = 0; i < n; ++i) sp[i][0] = {a[i], convert_to_psc(-convert_to_int(a[i]))};
- for (int j = 1; j < LOG; ++j) {
- for (int i = 0; i + (1 << j) <= n; ++i) {
- sp[i][j] = {Min(sp[i][j - 1].fi, sp[i + (1 << (j - 1))][j - 1].fi),
- Min(sp[i][j - 1].se, sp[i + (1 << (j - 1))][j - 1].se)};
- }
- }
- }
- psc get_min(int l, int r) {
- int j = __lg(r - l + 1);
- return Min(sp[l][j].fi, sp[r - (1 << j) + 1][j].fi);
- }
- psc get_max(int l, int r) {
- int j = __lg(r - l + 1);
- return Min(sp[l][j].se, sp[r - (1 << j) + 1][j].se);
- }
- };
- const int N = 524287;
- vector<int> lcp;
- pair<vector<psc>, sparse_table> t[N];
- void build(int id, int l, int r) {
- if (l + 1 == r) { t[id].fi = {convert_to_psc(lcp[l])}; t[id].se = sparse_table({convert_to_psc(l)}); return; }
- build(id * 2 + 1, l, l + r >> 1);
- build(id * 2 + 2, l + r >> 1, r);
- vector<pss> new_v, v1, v2;
- for (int i = 0; i < t[id * 2 + 1].fi.size(); ++i) v1.push_back({t[id * 2 + 1].fi[i], t[id * 2 + 1].se.sp[i][0].fi});
- for (int i = 0; i < t[id * 2 + 2].fi.size(); ++i) v2.push_back({t[id * 2 + 2].fi[i], t[id * 2 + 2].se.sp[i][0].fi});
- merge(all(v1), all(v2), back_inserter(new_v));
- vector<psc> nums, idxs;
- for (auto el : new_v) { nums.push_back(el.fi); idxs.push_back(el.se); }
- t[id].fi = nums;
- t[id].se = sparse_table(idxs);
- }
- psc get_left(int id, int l, int r, int i) {
- if (l >= i) { return convert_to_psc(-1); }
- if (r <= i) {
- int last = bin_search(t[id].fi, convert_to_psc(lcp[i])) - 1;
- return (last == -1 ? convert_to_psc(-1) : convert_to_psc(-convert_to_int(t[id].se.get_max(0, last))));
- }
- psc left = get_left(id * 2 + 1, l, l + r >> 1, i);
- psc right = get_left(id * 2 + 2, l + r >> 1, r, i);
- return Max(left, right);
- }
- psc get_right(int id, int l, int r, int i) {
- if (r <= i) { return convert_to_psc(N); }
- if (l >= i) {
- int last = bin_search(t[id].fi, convert_to_psc(lcp[i])) - 1;
- return (last == -1 ? convert_to_psc(N) : t[id].se.get_min(0, last));
- }
- psc left = get_right(id * 2 + 1, l, l + r >> 1, i);
- psc right = get_right(id * 2 + 2, l + r >> 1, r, i);
- return Min(left, right);
- }
- void count_sort(vector<int> &p, vector<int> &c) {
- int n = p.size();
- vector<int> pos(n + 1), p_new(n);
- for (auto x : c) {
- pos[x + 1]++;
- }
- for (int i = 1; i < n; ++i) pos[i] += pos[i - 1];
- for (auto x : p) {
- int i = c[x];
- p_new[pos[i]] = x;
- pos[i]++;
- }
- p = p_new;
- }
- void build(string &s, vector<int> &p, vector<int> &c) {
- int n = p.size();
- vector<pair<char, int>> a(n);
- for (int i = 0; i < n; ++i) a[i] = {s[i], i};
- sort(all(a));
- for (int i = 0; i < n; ++i) p[i] = a[i].se;
- for (int i = 1; i < n; ++i) {
- c[p[i]] = c[p[i - 1]];
- if (a[i].fi != a[i - 1].fi) ++c[p[i]];
- }
- int k = 0;
- while ((1 << k) < n) {
- for (int i = 0; i < n; ++i) {
- p[i] = (p[i] - (1 << k) + n) % n;
- }
- count_sort(p, c);
- vector<int> c_new(n);
- for (int i = 1; i < n; ++i) {
- pii prev = {c[p[i - 1]], c[(p[i - 1] + (1 << k)) % n]};
- pii now = {c[p[i]], c[(p[i] + (1 << k)) % n]};
- c_new[p[i]] = c_new[p[i - 1]];
- if (prev != now) ++c_new[p[i]];
- }
- c = c_new;
- ++k;
- }
- }
- void build_lcp(string &s, vector<int> &p, vector<int> &c) {
- int n = p.size();
- int cur_lcp = 0;
- for (int i = 0; i < n - 1; ++i) {
- int j = p[c[i] - 1];
- while (s[i + cur_lcp] == s[j + cur_lcp]) cur_lcp++;
- lcp[c[i]] = cur_lcp;
- cur_lcp = max(cur_lcp - 1, 0);
- }
- }
- int main() {
- fast
- // file_in
- // file_in_out
- int n, m;
- cin >> n >> m;
- vector<short> v_string(n);
- cin >> v_string;
- string s;
- for (auto el : v_string) s += el + '0';
- s += "$"; ++n;
- vector<int> p(n), c(n); lcp.resize(n);
- build(s, p, c); build_lcp(s, p, c);
- ll ans = 0;
- string ref;
- build(0, 0, n);
- for (int i = 0; i < n; ++i) {
- int left = convert_to_int(get_left(0, 0, n, i));
- int right = min(n, convert_to_int(get_right(0, 0, n, i)));
- if (ans < 1ll * lcp[i] * (right - left)) {
- ans = 1ll * lcp[i] * (right - left);
- ref = s.substr(p[i], lcp[i]);
- }
- }
- if (ans < s.size() - 1) {
- ans = s.size() - 1;
- ref = s; ref.pop_back();
- }
- cout << ans << '\n';
- cout << ref.size() << '\n';
- for (auto el : ref) {
- if (el == ':') {
- cout << 10 << " ";
- } else {
- cout << el << " ";
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement