Submission #374180

#TimeUsernameProblemLanguageResultExecution timeMemory
374180srvltPalinilap (COI16_palinilap)C++17
100 / 100
186 ms25068 KiB
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define mem(x, y) memset(& x, y, sizeof(x))
#define all(x) begin(x), end(x)
#define SZ(x) (int)(x).size()
#define cerr if(dbg)cerr
using namespace std;

const int n0=1e5+123;
int n;
string s;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
namespace Sol {
	bool dbg=0;
	ll mul[n0],add[n0],positive[n0][26],init;
	namespace Hash {
		const array<int,2> mod={(int)1e9+7,(int)1e9+9};
		int base=uniform_int_distribution<int>(27,(int)1e9)(rng);
		struct mint {
			array<int,2> x;
			mint(int val=0) {
				x[0]=x[1]=val;
			}
			void operator *= (const mint &a) {
				x[0]=(ll)x[0]*a.x[0]%mod[0];
				x[1]=(ll)x[1]*a.x[1]%mod[1];
			}
			void operator += (const mint &a) {
				x[0]+=a.x[0];if(x[0]>=mod[0]) x[0]-=mod[0];
				x[1]+=a.x[1];if(x[1]>=mod[1]) x[1]-=mod[1];
			}
			void operator -= (const mint &a) {
				x[0]-=a.x[0];if(x[0]<0) x[0]+=mod[0];
				x[1]-=a.x[1];if(x[1]<0) x[1]+=mod[1];
			}
			mint operator * (const mint &a) {
				mint res=*this;
				res*=a;
				return res;
			}
			mint operator + (const mint &a) {
				mint res=*this;
				res+=a;
				return res;
			}
			mint operator - (const mint &a) {
				mint res=*this;
				res-=a;
				return res;
			}
			bool operator == (const mint &a) {
				return x[0]==a.x[0] && x[1]==a.x[1];
			}
		};
		mint pref[n0],suf[n0],pw[n0];
		void build() {
			pw[0]=1;
			for(int i=1; i<=n; i++) {
				pw[i]=pw[i-1]*base;
				pref[i]=pref[i-1]+pw[i]*(s[i-1]-'a'+1);
			}
			for(int i=n; i>=1; i--) {
				suf[i]=suf[i+1]+pw[n-i+1]*(s[i-1]-'a'+1);
			}
		};
		mint get(int l,int r) {
			return pw[n-r]*(pref[r]-pref[l-1]);
		}
		mint get_rev(int l,int r) {
			return pw[l-1]*(suf[l]-suf[r+1]);
		}
		void clear() {
			for(int i=0; i<n0; i++) {
				pref[i]=suf[i]=pw[i]=0;
			}
		};
	}
	bool pal(int l,int r,int l2,int r2) {
		if(l<1 || l2<1 || r>n || r2>n) return 0;
		return Hash::get(l,r)==Hash::get_rev(l2,r2);
	}
	int find(int L,int R) {
		int l=-1,r=n;
		while(l<r-1) {
			int mid=l+r>>1;
			if(pal(L-mid,L,R,R+mid)) l=mid;
			else r=mid;
		}
		return l;
	}
	void add_inc(int l,int r,int x) {
		//(x-l)+i
		add[l]+=x-l,add[r+1]-=x-l;
		mul[l]++,mul[r+1]--;
	}
	void add_dec(int l,int r,int x) {
		//(x+l)-i
		add[l]+=x+l,add[r+1]-=x+l;
		mul[l]--,mul[r+1]++;
	}
	ll get(int pos) {
		return add[pos]+mul[pos]*pos;
	}
	void process(int L,int R) {
		int a=find(L,R);
		init+=a+1;
		int b=find(L-a-2,R+a+2);
		cerr << "process(" << L << "," << R << ")={" << a << "," << b << "}\n";
		if(L-a-1>=1 && R+a+1<=n) {
			positive[L-a-1][s[R+a]-'a']+=1+(b+1);
			positive[R+a+1][s[L-a-2]-'a']+=1+(b+1);
		}
		if(a>=0) {
			cerr << "neg\n";
			cerr << "inc: " << L-a << ' ' << L << ",start=" << -1 << '\n';
			cerr << "dec: " << R << ' ' << R+a << ",start=" << -a-1 << '\n';
			add_dec(L-a,L,-1);
			add_inc(R,R+a,-a-1);
		}
	}
	void clear() {
		Hash::clear();
		mem(mul,0),mem(add,0),mem(positive,0),init=0;
	};
	ll solve(bool _dbg) {
		dbg=_dbg;
		clear();
		Hash::build();
		for(int i=1; i<=n-1; i++) process(i,i+1);
		for(int i=1; i<=n-2; i++) process(i,i+2);
		init+=n;
		ll ans=init;
		cerr << "init=" << ans << '\n';
		for(int i=1; i<=n; i++) {
			add[i]+=add[i-1];
			mul[i]+=mul[i-1];
			ll diff=get(i);
			ll cur=0;
			for(int j=0; j<26; j++) {
				cur=0;
				if(s[i-1]-'a'!=j) cur+=diff;
				cur+=positive[i][j];
				ans=max(ans,init+cur);
			}
		}
		cerr << "neg[1]=" << get(1) << '\n';
		cerr << "positive[1][1]=" << positive[1][1] << '\n';
		return ans;
	};
}
namespace Slow {
	bool dbg=0;
	ll count(string x) {
		ll res=0;
		for(int i=0; i<SZ(x); i++) {
			for(int j=i; j<SZ(x); j++) {
				int ok=1;
				for(int k=i; k<=j; k++) {
					int t=j-(k-i);
					if(x[k]!=x[t]) {
						ok=0;
						break;
					}
				}
				if(ok) {
					res++;
				}
			}
		}
		return res;
	}
	ll solve(bool _dbg) {
		ll ans=0;
		string ans_t;
		for(int i=0; i<n; i++) {
			string t=s;
			for(int j=0; j<26; j++) {
				t[i]=char('a'+j);
				ll val=count(t);
				if(ans<val) {
					ans=val;
					ans_t=t;
				}
			}
		}
		cerr << ans_t << '\n';
		return ans;
	}
}
namespace Gen {
	uniform_int_distribution<int> _n(1,5),_c(0,5);
	void gen() {
		s="";
		n=_n(rng);
		for(int i=0; i<n; i++) s+=char('a'+_c(rng));
	}
	void output() {
		cout << n << '\n';
		cout << s << '\n';
	};
}

int main() {
	ios_base::sync_with_stdio(0), cin.tie(0);
	cin >> s;
	n=SZ(s);
	//ll sol=Sol::solve(1);
	//ll slow=Slow::solve(1);
	//cout << sol << ' ' << slow;
	cout << Sol::solve(0);
	
	//int tc=100000;
	//while(tc--) {
		//Gen::gen();
		//ll sol=Sol::solve(0),slow=Slow::solve(0);
		//if(sol!=slow) {
			//cout << "WA\n";
			//Gen::output();
			//cout << "expected=" << slow << ", output=" << sol << '\n';
			//return 0;
		//}
	//}
	//cout << "OK";
}

Compilation message (stderr)

palinilap.cpp: In function 'int Sol::find(int, int)':
palinilap.cpp:86:13: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   86 |    int mid=l+r>>1;
      |            ~^~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...