Submission #707477

#TimeUsernameProblemLanguageResultExecution timeMemory
707477DennisTranPalindromes (APIO14_palindrome)C++17
76 / 100
609 ms43632 KiB
#pragma GCC optimize("O2") #pragma GCC target("avx,avx2,fma") #include <bits/stdc++.h> #define FOR(i, a, b) for (int i = (a); i <= (b); i++) #define FOD(i, a, b) for (int i = (a); i >= (b); i--) #define REP(i, n) for (int i = 0; i < (n); i++) #define ALL(x) (x).begin(), (x).end() #define TIME (1.0 * clock() / CLOCKS_PER_SEC) #define file(name) if (fopen(name".inp", "r")) { freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); } using namespace std; mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count()); int Rand(int l, int r) { return l + rnd() % (r - l + 1); } struct SUFFIX_ARRAY{ vector<int> sort_cyclic_shifts(string const& s) { int n = s.size(); const int alphabet = 256; vector<int> p(n), c(n), cnt(max(alphabet, n), 0); for (int i = 0; i < n; i++) cnt[s[i]]++; for (int i = 1; i < alphabet; i++) cnt[i] += cnt[i - 1]; for (int i = 0; i < n; i++) p[--cnt[s[i]]] = i; c[p[0]] = 0; int classes = 1; for (int i = 1; i < n; i++) { if (s[p[i]] != s[p[i-1]]) classes++; c[p[i]] = classes - 1; } vector<int> pn(n), cn(n); for (int h = 0; (1 << h) < n; ++h) { for (int i = 0; i < n; i++) { pn[i] = p[i] - (1 << h); if (pn[i] < 0) pn[i] += n; } fill(cnt.begin(), cnt.begin() + classes, 0); for (int i = 0; i < n; i++) cnt[c[pn[i]]]++; for (int i = 1; i < classes; i++) cnt[i] += cnt[i - 1]; for (int i = n - 1; i >= 0; i--) p[--cnt[c[pn[i]]]] = pn[i]; cn[p[0]] = 0; classes = 1; for (int i = 1; i < n; i++) { pair<int, int> cur = {c[p[i]], c[(p[i] + (1 << h)) % n]}; pair<int, int> prev = {c[p[i-1]], c[(p[i-1] + (1 << h)) % n]}; if (cur != prev) ++classes; cn[p[i]] = classes - 1; } c.swap(cn); } return p; } vector<int> suffix_array(string s) { s += "$"; vector<int> sorted_shifts = sort_cyclic_shifts(s); sorted_shifts.erase(sorted_shifts.begin()); return sorted_shifts; } vector<int> kasai(string txt, vector<int> suffixArr) { int n = suffixArr.size(); vector<int> lcp(n, 0); vector<int> invSuff(n, 0); for (int i = 0; i < n; i++) invSuff[suffixArr[i]] = i; int k = 0; for (int i = 0; i < n; i++) { if (invSuff[i] == n - 1) { k = 0; continue; } int j = suffixArr[invSuff[i]+1]; while (i + k < n && j + k < n && txt[i + k] == txt[j + k]) k++; lcp[invSuff[i]] = k; if (k > 0) k--; } return lcp; } } T; const int MAXN = 3e5 + 5; const int MOD = 1e9 + 7; int N, f[20][MAXN], pos[MAXN], Hash[2 * MAXN], Pow[2 * MAXN]; int suff[MAXN]; int get_lcp(int l, int r) { if (l == r) return N - l + 1; l = pos[l]; r = pos[r]; if (l > r) swap(l, r); r--; int k = 31 - __builtin_clz(r - l + 1); return min(f[k][l], f[k][r - (1 << k) + 1]); } void Construct(string s) { N = s.size(); vector <int> sa = T.suffix_array(s); vector <int> lcp = T.kasai(s, sa); REP(i, N) { pos[sa[i] + 1] = i + 1; f[0][i + 1] = lcp[i]; suff[i + 1] = sa[i] + 1; } for (int i = 1; (1 << i) <= N; i++) for (int j = 1; j <= N - (1 << i) + 1; j++) f[i][j] = min(f[i - 1][j], f[i - 1][j + (1 << i - 1)]); } void Hashing(string s) { string t = s; reverse(ALL(t)); s = ' ' + s + t; Pow[0] = 1; FOR(i, 1, 2 * N) { Hash[i] = (1ll * Hash[i - 1] * 31 + s[i] - 'a') % MOD; Pow[i] = 31ll * Pow[i - 1] % MOD; } } int code(int l, int r) { return (Hash[r] - 1ll * Hash[l - 1] * Pow[r - l + 1] % MOD + MOD) % MOD; } bool is_palindrome(int l, int r) { int u = l + r >> 1; int v = u + 1; if ((r - l + 1) & 1) v--; r = N - r + 1 + N; v = N - v + 1 + N; return code(l, u) == code(r, v); } vector <pair <int, int>> Distinct_palindrome_substring(string s) { vector <pair <int, int>> ans; unordered_map <int, bool> dd; FOR(i, 1, N) { int l = 0, r = min(i, N - i + 1); while (r - l > 1) { int mid = l + r >> 1; if (is_palindrome(i - mid, i + mid)) l = mid; else r = mid; } int len = l; l = i - len, r = i + len; while (r >= l) { if (dd[code(l, r)]) break; dd[code(l, r)] = 1; ans.emplace_back(l, r); l++; r--; } if (i < N && s[i] == s[i + 1]) { int l = 0, r = min(i, N - i); while (r - l > 1) { int mid = l + r >> 1; if (is_palindrome(i - mid, i + mid + 1)) l = mid; else r = mid; } len = l; l = i - len, r = i + 1 + len; while (r >= l) { if (dd[code(l, r)]) break; dd[code(l, r)] = 1; ans.emplace_back(l, r); l++; r--; } } } return ans; } bool Lower_bound(int l, int r, int mid, string &s) { int len = get_lcp(l, mid); len = min(len, r - l + 1); if (len == r - l + 1) return true; if (len == N - mid + 1) return false; return s[l + len] < s[mid + len]; } bool Upper_bound(int l, int r, int mid, string &s) { int len = get_lcp(l, mid); len = min(len, r - l + 1); if (len == r - l + 1) return false; if (len == N - mid + 1) return false; return s[l + len] < s[mid + len]; } int count_occurences(int l, int r, string &s) { int L = 0, R = N + 1; while (R - L > 1) { int mid = L + R >> 1; if (Lower_bound(l, r, suff[mid], s)) R = mid; else L = mid; } int u = R, v = 0; L = 0, R = N + 1; while (R - L > 1) { int mid = L + R >> 1; if (Upper_bound(l, r, suff[mid], s)) R = mid; else L = mid; } v = R - 1; return v - u + 1; } signed main(void) { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); //int T; cin >> T; while (T--) file("TASK"); string s; cin >> s; Construct(s); Hashing(s); s = ' ' + s; auto sets = Distinct_palindrome_substring(s); long long ans = 0; for (auto x : sets) { ans = max(ans, count_occurences(x.first, x.second, s) * (x.second - x.first + 1ll)); } cout << ans; cerr << "Time elapsed: " << TIME << " s.\n"; return (0 ^ 0); }

Compilation message (stderr)

palindrome.cpp: In function 'int get_lcp(int, int)':
palindrome.cpp:88:5: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
   88 |     if (l > r) swap(l, r); r--;
      |     ^~
palindrome.cpp:88:28: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
   88 |     if (l > r) swap(l, r); r--;
      |                            ^
palindrome.cpp: In function 'void Construct(std::string)':
palindrome.cpp:107:61: warning: suggest parentheses around '-' inside '<<' [-Wparentheses]
  107 |             f[i][j] = min(f[i - 1][j], f[i - 1][j + (1 << i - 1)]);
      |                                                           ~~^~~
palindrome.cpp: In function 'bool is_palindrome(int, int)':
palindrome.cpp:126:15: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  126 |     int u = l + r >> 1;
      |             ~~^~~
palindrome.cpp: In function 'std::vector<std::pair<int, int> > Distinct_palindrome_substring(std::string)':
palindrome.cpp:140:25: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  140 |             int mid = l + r >> 1;
      |                       ~~^~~
palindrome.cpp:156:29: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  156 |                 int mid = l + r >> 1;
      |                           ~~^~~
palindrome.cpp: In function 'int count_occurences(int, int, std::string&)':
palindrome.cpp:192:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  192 |         int mid = L + R >> 1;
      |                   ~~^~~
palindrome.cpp:199:21: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  199 |         int mid = L + R >> 1;
      |                   ~~^~~
palindrome.cpp: In function 'int main()':
palindrome.cpp:9:58: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
    9 | #define file(name)  if (fopen(name".inp", "r")) { freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); }
      |                                                   ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
palindrome.cpp:210:5: note: in expansion of macro 'file'
  210 |     file("TASK");
      |     ^~~~
palindrome.cpp:9:91: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
    9 | #define file(name)  if (fopen(name".inp", "r")) { freopen(name".inp", "r", stdin); freopen(name".out", "w", stdout); }
      |                                                                                    ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
palindrome.cpp:210:5: note: in expansion of macro 'file'
  210 |     file("TASK");
      |     ^~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...