Submission #646884

#TimeUsernameProblemLanguageResultExecution timeMemory
646884amoo_safarPalindromes (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...