Submission #1137966

#TimeUsernameProblemLanguageResultExecution timeMemory
1137966Math4Life2020Palindromes (APIO14_palindrome)C++20
47 / 100
590 ms174796 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long; using pii = pair<ll,ll>;
const ll a = 1234567; const ll p = 1e9+7; //hash values 
ll ans = 0;

const ll Nm = 6e5+5; ll N;
ll aexp[Nm+1];

ll phsh[Nm+1];
ll pihsh[Nm+1];
ll tval[Nm];
ll prad[Nm]; //permutation radius

ll ghsh(ll l, ll r) { //[l,r]
	ll v = phsh[r+1]-aexp[r+1-l]*phsh[l];
	v = (v+p*(-v/p+2))%p;
	return v;
}

ll gihsh(ll l0, ll r0) { //[l,r]
	ll l = Nm-1-r0; ll r = Nm-1-l0;
	ll v = pihsh[r+1]-aexp[r+1-l]*pihsh[l];
	v = (v+p*(-v/p+2))%p;
	return v;
}

unordered_map<ll,ll> fdeg; //forward degree (hash -> children)
unordered_map<ll,ll> radj; //reverse adjacency (parent -> this)
unordered_map<ll,ll> hrad; //radius of hash
unordered_map<ll,ll> ival; //intrinsic value

inline void aug(unordered_map<ll,ll>& m0, ll v, ll del=1) {
	if (m0.find(v)!=m0.end()) {
		m0[v]+=del;
	} else {
		m0[v]=del;
	}
}

//ll CLOCK = 0;

void process(vector<ll> velem, ll l, ll r) {
	// cout << "process: l,r="<<l<<","<<r<<"\nvelem:\n";
	// for (ll x: velem) {
	// 	cout << x << " ";
	// }
	// cout << "\n";
	// if (CLOCK++>=4) {
	// 	exit(0);
	// }
	if (velem.size()==0) {
		return;
	}
	ll M = velem.size();
	vector<ll> v0,v1;
	for (ll i=0;i<M;i++) {
		ll x = velem[i];
		if (prad[x]>=l) {
			v0.push_back(ghsh(x,x+l));
			hrad[v0[i]]=l;
			aug(ival,v0[i],0);
			aug(fdeg,v0[i],0);
		} else {
			assert(1==2);
			v0.push_back(-1);
		}
	}
	for (ll i=0;i<M;i++) {
		ll x = velem[i];
		if (prad[x]>=r) {
			v1.push_back(ghsh(x,x+r));
			hrad[v1[i]]=r;
			aug(ival,v1[i],0);
			aug(fdeg,v1[i],0);
		} else {
			v1.push_back(-1);
		}
	}
	//v1 shouldn't have repeats other than -1s
	//repeats possibly present in v0? also no -1s
	if ((r-1)==l) { //process
		for (ll i=0;i<M;i++) {
			if (v1[i]==-1) {
				aug(ival,v0[i]);
				// cout << "aug ival for x,rad="<<velem[i]<<","<<l<<"\n";
				radj[v0[i]]=-1;
			} else {
				radj[v1[i]]=v0[i];
				aug(fdeg,v0[i]);
			}
		}
		return;
	} 
	if (M==1) {
		if (v1[0]!=-1) {
			radj[v1[0]]=v0[0];
			aug(fdeg,v0[0]);
		} else {
			ll shsh = ghsh(velem[0],velem[0]+prad[velem[0]]);
			if (shsh==v0[0]) {
				aug(ival,v0[0]);
				radj[v0[0]]=-1;
			} else {
				aug(ival,shsh);
				radj[shsh]=v0[0];
				aug(fdeg,v0[0]);
				aug(fdeg,shsh,0);
				hrad[shsh]=prad[velem[0]];
			}
		}
		return;
	}
	ll xn = (l+r)/2;
	vector<ll> v2;
	for (ll i=0;i<M;i++) {
		ll x = velem[i];
		if (prad[x]>=xn) {
			v2.push_back(ghsh(x,x+xn));
			hrad[v2[i]]=xn;
			aug(ival,v2[i],0);
			aug(fdeg,v2[i],0);
		} else {
			v2.push_back(-1);
		}
	}
	// unordered_map<ll,vector<ll>> vhsh;
	// for (ll i=0;i<M;i++) {
	// 	vhsh[v2[i]].push_back(velem[i]);
	// }
	// vector<ll> pr1;
	// for (auto A0: vhsh) {
	// 	if (A0.first!=-1) {
	// 		process(A0.second,xn,r);
	// 		pr1.push_back((A0.second)[0]);
	// 	} else {
	// 		for (ll x: A0.second) {
	// 			pr1.push_back(x);
	// 		}
	// 	}
	// }
	// process(pr1,l,xn);
	unordered_map<ll,vector<ll>> vhsh;
	for (ll i=0;i<M;i++) {
		vhsh[v2[i]].push_back(i);
	}
	vector<ll> pr1;
	for (auto A0: vhsh) {
		if (A0.first!=-1) {
			vector<ll> vpr;
			for (ll x: A0.second) {
				vpr.push_back(velem[x]);
			}
			process(vpr,xn,r);
			pr1.push_back((A0.second)[0]);
		} else {
			for (ll x: A0.second) {
				pr1.push_back(x);
			}
		}
	}
	// cout << "processing back: l,r="<<l<<","<<r<<"\n";
	// cout << "pr1 size="<<pr1.size()<<"\n";
	unordered_map<ll,vector<ll>> vhsh1;
	for (ll x: pr1) {
		vhsh1[v0[x]].push_back(velem[x]);
	}
	for (auto A0: vhsh1) {
		process(A0.second,l,xn);
	}
}

queue<ll> q0;

int main() {
	mt19937 gen((long long) new char);
	aexp[0]=1;
	for (ll i=0;i<Nm;i++) {
		aexp[i+1]=(a*aexp[i])%p;
	}
	ios_base::sync_with_stdio(false); cin.tie(0);
	string s; cin >> s;
	string t="|";
	N = s.length();
	for (ll i=0;i<N;i++) {
		t += s.substr(i,1);
		t+="|";
	}
	N=t.length(); 
	//cout << "N="<<N<<"\n";
	for (ll i=0;i<N;i++) {
		tval[i]=t[i];
	}
	// for (ll i=N;i<Nm;i++) {
	// 	tval[i]=gen();
	// }
	phsh[0]=0;
	for (ll i=0;i<Nm;i++) {
		phsh[i+1]=(tval[i]+a*phsh[i])%p;
	}
	pihsh[0]=0;
	for (ll i=0;i<Nm;i++) {
		pihsh[i+1]=(tval[Nm-1-i]+a*pihsh[i])%p;
	}
	vector<ll> vall;
	for (ll i=0;i<N;i++) { //get radii
		vall.push_back(i);
		ll rmin = 0;
		ll rmax = min(i,N-1-i);
		while (rmin<rmax) {
			ll rt = (rmin+rmax+1)/2;
			if (ghsh(i,i+rt)==gihsh(i-rt,i)) {
				rmin = rt;
			} else {
				rmax = rt-1;
			}
		}
		prad[i]=rmin;
		//cout << "prad[i="<<i<<"]="<<prad[i]<<"\n";
	}
	process(vall,0,N+5);
	//cout << "ghsh: "<<ghsh(1,2)<<"\n";
	for (pii p0: fdeg) {
		if (p0.second==0) {
			q0.push(p0.first);
		}
	}
	while (!q0.empty()) {
		ll hv = q0.front(); q0.pop();
		//cout << "process hv = "<<hv<<"\n";
		ll rhv = hrad[hv];
		ll ncnt = ival[hv];
		//cout << "rhv,ncnt="<<rhv<<","<<ncnt<<"\n";
		ans = max(ans,rhv*ncnt);
		ll rad = radj[hv];
		if (rad != -1) {
			fdeg[rad]--;
			if (fdeg[rad]==0) {
				q0.push(rad);
			}
			aug(ival,rad,ival[hv]);
		}
	}
	if (ghsh(0,N-1)==gihsh(0,N-1)) {
		ans = max(ans,(N-1)/2);
	}
	cout << ans << "\n";
}
#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...