Submission #532969

#TimeUsernameProblemLanguageResultExecution timeMemory
532969codr0Palindromes (APIO14_palindrome)C++14
73 / 100
1047 ms56796 KiB
// Code by Parsa Eslami
 
#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#define pii pair<int,int>
#define bit(i,j) ((j>>i)&1)
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FORR(i,a,b) for(int i=a;i>=b;i--)
#define S second
#define F first
#define pb push_back
#define SZ(x) (int)x.size()
#define all(x) x.begin(),x.end()
#define err(x) cout<<#x<<": "<<x<<'\n';
 
using namespace std;
const int BASE=131;
const int MOD=998765431;
const int N=3e5+1e4;
struct fenwick{
	int fen[2*N],S,pw[20];
	fenwick(){
		pw[0]=1;
		FOR(i,1,19) pw[i]=pw[i-1]*2;
	}
	void insert(int k){
		if(!k){
			S++;
			return;
		}
		while(k<2*N){
			fen[k]++;
			k+=(k&(-k));
		}
	}
	int get(int k){
		int rt=S;
		while(k>0){
			rt+=fen[k];
			k-=(k&(-k));
		}
		return rt;
	}
	void clear(){
		FOR(i,0,2*N-1) fen[i]=0;
		S=0;
	}
	int BSR(int X){
		int val=get(X);
		int ind=0;
		int sum=S;
		FORR(j,19,0) if(ind+pw[j]<2*N&&sum+fen[ind+pw[j]]<=val){
			sum+=fen[ind+pw[j]];
			ind+=pw[j];
		}
		return (ind+1);
	}
	int BSL(int X){
		int val=get(X)-1;
		if(val==S-1) return 0;
		int ind=0;
		int sum=S;
		FORR(j,19,0) if(ind+pw[j]<2*N&&sum+fen[ind+pw[j]]<=val){
			sum+=fen[ind+pw[j]];
			ind+=pw[j];
		}
		return (ind+1);
	}
};fenwick fen;
string s;
int n;
int arr[2*N];
int hshR[N],hsh[N];
int PAL[2*N];
int pw[N],inv[N];

vector<int> suffix_array(string S){
  S.push_back(0);
  int N = S.size();
  vector<int> cnt(128, 0);
  for (int i = 0; i < N; i++){
    cnt[S[i]]++;
  }
  for (int i = 0; i < 127; i++){
    cnt[i + 1] += cnt[i];
  }
  vector<int> SA(N);
  for (int i = 0; i < N; i++){
    cnt[S[i]]--;
    SA[cnt[S[i]]] = i;
  }
  vector<int> rank(N);
  rank[SA[0]] = 0;
  for (int i = 0; i < N - 1; i++){
    rank[SA[i + 1]] = rank[SA[i]];
    if (S[SA[i]] != S[SA[i + 1]]){
      rank[SA[i + 1]]++;
    }
  }
  int L = 1;
  while (L < N){
    vector<int> SA2(N);
    for (int i = 0; i < N; i++){
      SA2[i] = SA[i] - L;
      if (SA2[i] < 0){
        SA2[i] += N;
      }
    }
    cnt = vector<int>(N, 0);
    for (int i = 0; i < N; i++){
      cnt[rank[SA2[i]]]++;
    }
    for (int i = 0; i < N - 1; i++){
      cnt[i + 1] += cnt[i];
    }
    for (int i = N - 1; i >= 0; i--){
      cnt[rank[SA2[i]]]--;
      SA[cnt[rank[SA2[i]]]] = SA2[i];
    }
    vector<int> rank2(N);
    rank2[SA[0]] = 0;
    for (int i = 0; i < N - 1; i++){
      rank2[SA[i + 1]] = rank2[SA[i]];
      if (rank[SA[i]] != rank[SA[i + 1]] || rank[(SA[i] + L) % N] != rank[(SA[i + 1] + L) % N]){
        rank2[SA[i + 1]]++;
      }
    }
    rank = rank2;
    L *= 2;
  }
  SA.erase(SA.begin());
  return SA;
}

	inline int mul(int a,int b){
		int rt=(1LL*a*b)%MOD;
		return rt;
	}

	inline int mkey(int a,int b){
		int rt=a+b;
		if(rt<0) rt+=MOD;
		if(rt>=MOD) rt-=MOD;
		return rt;
	}

	int HSH(int l,int r){
		int rt=mkey(hsh[r],-hsh[l-1]);
		rt=mul(rt,inv[l-1]);
		return rt;
	}

	int HSHR(int l,int r){
		int rt=mkey(hshR[l],-hshR[r+1]);
		rt=mul(rt,inv[n-r]);
		return rt;
	}

	int PW(int a,int b){
		if(!b) return 1;
		int rt=PW(a,b/2);
		rt=mul(rt,rt);
		if(b&1) rt=mul(rt,a);
		return rt;
	}

	int lcp(int I,int J){
		int l=0,r=n+1;
		while(r-l>1){
			int mid=(r+l)/2;
			if(max(I,J)+mid>(n+1)) r=mid;
			else if(HSH(I,I+mid-1)==HSH(J,J+mid-1)) l=mid;
			else r=mid;
		}
		return l;
	}

	int pal(int i,int j){
		int l=0,r=n+1;
		while(r-l>1){
			int mid=(r+l)/2;
			if(i-mid<0||j+mid>(n+1)) r=mid;
			else if(HSHR(i-mid+1,i)==HSH(j,j+mid-1)) l=mid;
			else r=mid;
		}
		return l;
	}

	int32_t main(){
	ios_base::sync_with_stdio(0); cin.tie(0);

	pw[0]=1; inv[0]=1; FOR(i,1,N-1) pw[i]=mul(pw[i-1],BASE),inv[i]=PW(pw[i],MOD-2);
	cin>>s; vector<int> X0=suffix_array(s); n=SZ(s);
	s='$'+s;
	hsh[0]=0;
	FOR(i,1,n) hsh[i]=mkey(hsh[i-1],mul((s[i]-'a'+1),pw[i-1]));
	hshR[n+1]=0;
	FORR(i,n,1) hshR[i]=mkey(hshR[i+1],mul((s[i]-'a'+1),pw[n-i]));
	int sa[n+1];
	FOR(i,1,n) sa[i]=X0[i-1]+1;	
	int to[n+1]; FOR(i,1,n) to[sa[i]]=i;
	int num[2*n]={};
	FOR(i,1,n){
		num[2*i-1]=pal(i,i);
		if(i!=n) num[2*i]=pal(i,i+1);
	}
	FOR(i,1,n){
		arr[2*i-1]=n+1-sa[i];
		if(i!=n) arr[2*i]=lcp(sa[i],sa[i+1]);
	}
	FOR(i,1,n){
		num[2*i-1]-=i;
		if(i!=n) num[2*i]-=i;
	}
	vector<int> ind[2*n];
	FOR(i,1,2*n-1) ind[num[i]+n].pb(i);
	FOR(j,n+1,2*n-1) for(int x0:ind[j]) fen.insert(x0);
	fen.insert(2*n+1);
	FOR(i,1,n){
		for(int x0:ind[n+1-i]) fen.insert(x0);
		int mid=0;
		mid=(i+n)/2;
		if((i+n)%2==0){
			mid=mid*2-1;
		}else{
			mid=mid*2;
		}
		int it=fen.BSL(mid);
		PAL[2*to[i]-1]=(it)-(2*i-1)+1;
		if(to[i]!=n&&arr[2*to[i]]){
			int X=i+arr[2*to[i]]-1;
			mid=(i+X)/2;
			if((i+X)%2==0){
				mid=mid*2-1;
			}else mid=mid*2;
			it=fen.BSL(mid);
			PAL[2*to[i]]=(it)-(2*i-1)+1;
		}
	}
	vector<pair<pii,int>> vc;
	FOR(i,1,2*n-1){
		vc.pb({{arr[i],i&1},i});
	}
	sort(all(vc));
	fen.clear();
	fen.insert(2*n);
	fen.insert(0);
	long long ans=0;
	FOR(i,0,2*n-2){
		int I=vc[i].S;
		int it=fen.BSR(I);
		int R=it; R--;
		it=fen.BSL(I);
		int L=it; L++;
		ans=max(ans,1LL*((R-L+2)/2)*PAL[I]);
		fen.insert(I);
	}
	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...