제출 #646884

#제출 시각아이디문제언어결과실행 시간메모리
646884amoo_safar회문 (APIO14_palindrome)C++17
92 / 100
544 ms82776 KiB
#include <bits/stdc++.h> #pragma GCC target ("avx2") #pragma GCC optimize("Ofast") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,fma,tune=native") #pragma GCC optimize("unroll-loops") #define pb push_back #define F first #define S second #define all(x) x.begin(), x.end() #define debug(x) cerr << #x << " : " << x << '\n' using namespace std; typedef long long ll; typedef long double ld; typedef string str; typedef pair<ll, ll> pll; typedef pair<int, int> pii; typedef pair<pll, pll> node; const ll Mod = 1e9 + 7; const int Maxn = 3e5 + 10; const int Maxk = 60; const ll Inf = 2242545357980376863LL; const int Log = 19; const ll Base = 998244353; int Rank[Log][Maxn], n; int idx[Maxn]; ll ph[Maxn], phr[Maxn], pw[Maxn]; pii a[Maxn]; vector<int> Rdx[Maxn]; vector<int> Rdx2[Maxn]; str s; ll get(int l, int r){ return (ph[r] - (ph[l]*pw[r - l] % Mod) + Mod) % Mod; } ll get_rev(int l, int r){ return (phr[l] - (phr[r]*pw[r - l] % Mod) + Mod) % Mod; } int pal_range(int l, int r){ int L = 0, R = min(n - r, l) + 1, mid; while(L + 1 < R){ mid = (L + R) >> 1; if(get(l - mid, l) == get_rev(r, r + mid)) L = mid; else R = mid; } return L; } int pal[Maxn]; int eq_range(int l1, int l2){ int L = 0, R = min(n - l1, n - l2) + 1, mid; //for(int i = 0; i + 1 < R; i++) if(s[i + l1] != s[i + l2]) return i; //return R - 1; while(L + 1 < R){ mid = (L + R) >> 1; if(get(l1, l1 + mid) == get(l2, l2 + mid)) L = mid; else R = mid; } return L; } int eq[Maxn]; int par[Maxn], sz[Maxn]; vector<int> Merge[Maxn]; vector<int> On[Maxn]; int get_par(int u){ if(par[u] == u) return u; return par[u] = get_par(par[u]); } void merge(int u, int v){ u = get_par(u); v = get_par(v); sz[u] += sz[v]; par[v] = par[u]; } int cnt[Maxn], ord[Maxn], ord2[Maxn]; int32_t main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); pw[0] = 1; for(int i = 1; i < Maxn; i++) pw[i] = (pw[i - 1] * Base) % Mod; cin >> s; n = s.size(); ph[0] = 0; for(int i = 1; i <= n; i++) ph[i] = (ph[i - 1] * Base + s[i - 1]) % Mod; phr[n] = 0; for(int i = n - 1; i >= 0; i--) phr[i] = (phr[i + 1] * Base + s[i]) % Mod; //cerr << get(0, 2) << " " << get(n-2, n) << '\n'; // vector<char> com; // for(auto c : s) com.pb(c); // sort(all(com)); for(int i = 0; i < n; i++) Rank[0][i] = (s[i] - 'a') + 1; // for(int i = 0; i < n; i++) // cerr << "! " << s.substr(i, 1) << ' ' << Rank[0][i] << '\n'; int st; for(int l = 1; l < Log; l++){ st = (1 << (l - 1)); for(int i = 0; i <= n; i++) cnt[i] = 0; for(int i = 0; i < n; i++){ // a[i].F = Rank[l - 1][i]; // a[i].S = (i + st < n ? Rank[l - 1][i + st] : -1); cnt[(i + st < n ? Rank[l - 1][i + st] : 0)] ++; } for(int i = 1; i <= n; i++) cnt[i] += cnt[i - 1]; for(int i = n - 1; i >= 0; i--) ord[-- cnt[(i + st < n ? Rank[l - 1][i + st] : 0)]] = i; for(int i = 0; i <= n; i++) cnt[i] = 0; for(int _i = 0; _i < n; _i++){ // a[i].F = Rank[l - 1][i]; // a[i].S = (i + st < n ? Rank[l - 1][i + st] : -1); cnt[Rank[l - 1][ord[_i]]] ++; } for(int i = 1; i <= n; i++) cnt[i] += cnt[i - 1]; for(int _i = n - 1; _i >= 0; _i--) ord2[-- cnt[Rank[l - 1][ord[_i]]]] = ord[_i]; int po = 1; for(int _i = 0; _i < n; _i ++){ Rank[l][ord2[_i]] = po; if(_i + 1 < n && (Rank[l - 1][ord2[_i]] != Rank[l - 1][ord2[_i + 1]] || ((ord2[_i + 1] + st < n ? Rank[l - 1][ord2[_i + 1] + st] : 0) != (ord2[_i] + st < n ? Rank[l - 1][ord2[_i] + st] : 0) ))) po ++; } // cerr << "---------------------\n"; // for(int i = 0; i < n; i++) // cerr << "! " << s.substr(i, 2 * st) << ' ' << Rank[l][i] << '\n'; // break; } // assert(n < 300000); for(int i = 0; i < n; i++) Rank[Log - 1][i] --; for(int i = 0; i < n; i++) idx[Rank[Log - 1][i]] = i; // for(int i = 0; i < n; i++) // cerr << "! " << s.substr(idx[i], n) << '\n'; for(int i = 0; i < n - 1; i++) eq[i] = eq_range(idx[i], idx[i + 1]); for(int i = 0; i < n - 1; i++) Merge[eq[i]].pb(i); ll ans = 0; for(int i = 0; i < n; i++) pal[i] = pal_range(i + 1, i); for(int i = 0; i < n; i++) On[pal[i]].pb(Rank[Log - 1][i]); iota(par, par + Maxn, 0); fill(sz, sz + Maxn, 0); int mx = 0; for(int x = n + 1; x >= 1; x--){ for(auto y : Merge[x]){ merge(y, y + 1); mx = max(mx, sz[get_par(y)]); } for(auto y : On[x]){ sz[get_par(y)] ++; mx = max(mx, sz[get_par(y)]); } ans = max(ans, 1LL * mx * (x + x - 1)); } for(int i = 0; i < n; i++) pal[i] = pal_range(i, i); for(int i = 0; i < Maxn; i++) On[i].clear(); for(int i = 0; i < Maxn; i++) On[pal[i]].pb(Rank[Log - 1][i]); iota(par, par + Maxn, 0); fill(sz, sz + Maxn, 0); mx = 0; for(int x = n + 1; x >= 1; x--){ for(auto y : Merge[x]){ merge(y, y + 1); mx = max(mx, sz[get_par(y)]); } for(auto y : On[x]){ sz[get_par(y)] ++; mx = max(mx, sz[get_par(y)]); } ans = max(ans, 1LL * mx * (x + x)); } cout << ans << '\n';; return 0; }
#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...