結果
問題 | No.765 ukuku 2 |
ユーザー |
![]() |
提出日時 | 2018-12-13 00:46:51 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,009 ms / 3,000 ms |
コード長 | 4,101 bytes |
コンパイル時間 | 2,273 ms |
コンパイル使用メモリ | 206,960 KB |
最終ジャッジ日時 | 2025-01-06 19:00:41 |
ジャッジサーバーID (参考情報) |
judge1 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 48 |
ソースコード
#include<bits/stdc++.h>using namespace std;const int M = 1000000007;class suffix_array {// compare (rank[i], rank[i + k]) and (rank[j], rank[j + k])static bool compare_sa(int n, const vector<int>& rank, int i, int j, int k) {if (rank[i] != rank[j]) return rank[i] < rank[j];int ri = i + k <= n ? rank[i + k] : -1;int rj = j + k <= n ? rank[j + k] : -1;return ri < rj;}public:static vector<int> construct_sa(const string& s) {int n = s.length();vector<int> sa(n + 1), rank(n + 1);for (int i = 0; i <= n; ++i) {sa[i] = i;rank[i] = i < n ? s[i] : -1;}for (int k = 1; k <= n; k <<= 1) {sort(sa.begin(), sa.end(), [&n, &k, &rank](const int& a, const int& b){ return compare_sa(n, rank, a, b, k); });vector<int> tmp(n + 1);for (int i = 1; i <= n; ++i)tmp[sa[i]] = tmp[sa[i - 1]] + compare_sa(n, rank, sa[i - 1], sa[i], k);for (int i = 0; i <= n; ++i)rank[i] = tmp[i];}return sa;}static vector<int> construct_lcp(const string& s, const vector<int>& sa) {int n = s.length();vector<int> rank(n + 1), lcp(n + 1);for (int i = 0; i <= n; ++i) rank[sa[i]] = i;int h = 0;for (int i = 0; i < n; ++i) {if (h > 0) --h;for (int j = sa[rank[i] - 1]; j + h < n && i + h < n; ++h)if (s[j + h] != s[i + h]) break;lcp[rank[i] - 1] = h;}return lcp;}};class segtree {private:int n, s, t;vector<int> tr;const int ex = M;int q(int k, int l, int r) {return r <= s || t <= l ? ex : s <= l && r <= t ? tr[k]: min(q(k << 1 | 1, l, (l + r) >> 1), q((k + 1) << 1, (l + r) >> 1, r));}public:segtree(int m) {n = 1;while (n < m) n <<= 1;tr = vector<int>((n << 1) - 1, ex);}void update(int j, const int& x) {int i = j + n - 1;tr[i] = x;while (i > 0) { i = (i - 1) >> 1; tr[i] = min(tr[i << 1 | 1], tr[(i + 1) << 1]); }}// [s, t)int run(int _s, int _t) { s = _s; t = _t; return q(0, 0, n); }};int main() {string s;cin >> s;int n = s.length();int m = n * 2 + 1;string rev = s;reverse(rev.begin(), rev.end());string ss = s + "#" + rev;vector<int> sa = suffix_array::construct_sa(ss);vector<int> lcp = suffix_array::construct_lcp(ss, sa);vector<int> rank(m + 1);segtree sg(m + 1);for (int i = 0; i <= m; ++i) {sg.update(i, lcp[i]);// cout << lcp[i] << "\n";rank[sa[i]] = i;}int ans = 1;for (int i = 1; i < n; ++i) {{int ri = i, li = m - i;int len = sg.run(min(rank[ri], rank[li]), max(rank[ri], rank[li]));ri += len;li += len;ans = max(ans, len * 2 - 2);if (ri <= n && li + 1 <= m) {int len1 = sg.run(min(rank[ri], rank[li + 1]), max(rank[ri], rank[li + 1]));ans = max(ans, len * 2 + len1 * 2);}if (ri + 1 <= n && li <= m) {int len1 = sg.run(min(rank[ri + 1], rank[li]), max(rank[ri + 1], rank[li]));ans = max(ans, len * 2 + len1 * 2);}}{int ri = i, li = m - i + 1;int len = sg.run(min(rank[ri], rank[li]), max(rank[ri], rank[li]));ri += len;li += len;ans = max(ans, len * 2);if (ri <= n && li + 1 <= m) {int len1 = sg.run(min(rank[ri], rank[li + 1]), max(rank[ri], rank[li + 1]));ans = max(ans, len * 2 + len1 * 2 + 1);}if (ri + 1 <= n && li <= m) {int len1 = sg.run(min(rank[ri + 1], rank[li]), max(rank[ri + 1], rank[li]));ans = max(ans, len * 2 + len1 * 2 + 1);}}}cout << ans << "\n";return 0;}