s**t 山求卡常
查看原帖
s**t 山求卡常
886055
MoonCake2011楼主2024/8/27 11:05
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
int s1[maxn*2],s2[maxn*2],power[maxn*2];
int tot,len,L;
char s[maxn*2];
string t;
#define mod 1000000007
const __int128 y=(__int128(1)<<64)/mod;
inline int MOD(long long x){
    int a=x-((x*y)>>64)*mod;
    if(a>mod) a-=mod;
    return a;
}
inline int gethash1(int l,int r){
	return MOD(s1[r]-MOD((long long)(s1[l-1])*power[r-l+1])+1000000007);
}
inline int gethash2(int l,int r){
	return MOD(s2[l]-MOD((long long)(s2[r+1])*power[r-l+1])+1000000007);
}
unordered_set<int>mp;
vector<pair<int,int> >MH;
int sa[300010],rk[300010],o[300010],w;
//inline bool cmp(int x,int y){
//	if(rk[x]==rk[y]) return rk[x+w]<rk[y+w];
//	return rk[x]<rk[y];
//}
int buc[300010],id[300010];
inline void binary(){
//	memset(buc,0,sizeof buc);
//	memset(id,0,sizeof id);
//	memset(o,0,sizeof o);
	int p=0,m=128;
	for(int i=1;i<=L;++i) buc[rk[i]=t[i]]++;
	for(int i=1;i<=m;++i) buc[i]+=buc[i-1];
	for(int i=L;i>=1;--i) sa[buc[rk[i]]--]=i;
	for(w=1;w<L;w<<=1,m=L){
		int tot=0;
		for(int i=L-w+1;i<=L;++i) id[++tot]=i;
		for(int i=1;i<=L;++i) if(sa[i]>w) id[++tot]=sa[i]-w;
		memset(buc,0,sizeof buc);
		for(int i=1;i<=L;++i) buc[rk[i]]++;
		for(int i=1;i<=m;++i) buc[i]+=buc[i-1];
		for(int i=L;i>=1;--i) sa[buc[rk[id[i]]]--]=id[i];
		memcpy(o,rk,sizeof o);
		for(int p=0,j=1;j<=L;j++)
			if(o[sa[j]]==o[sa[j-1]] && o[sa[j]+w]==o[sa[j-1]+w]) rk[sa[j]]=p;
			else rk[sa[j]]=++p;
	}
}
//int sp[600010],q[600010];
//inline void Hash(){
//	q[0]=1;
//	for(int i=1;i<=n;++i) q[i]=q[i-1]*131,sp[i]=sp[i-1]*131+s[i];
//}
//inline int get(int l,int r){
//	return sp[r]-sp[l-1]*q[r-l+1];
//}
int h[300010];
inline void height(){
	h[1]=0;
	for(int i=1,k=0;i<=L;++i){
		if(!rk[i]) continue;
		if(k) --k;
		while(i+k<=L && sa[rk[i]-1]+k<=L && t[i+k]==t[sa[rk[i]-1]+k]) ++k;
		h[rk[i]]=k;
	}
//	for(int i=2;i<=L;++i){
//		int x=sa[i-1],y=sa[i];
//		int len=max(L-x+1,L-y+1);
//		int p=0;
//		for(int j=30;j>=0;--j){
//			if(p+(1<<j)-1>len) continue;
//			if(gethash3(x,x+p+(1<<j)-1)==gethash3(y,y+p+(1<<j)-1)) p+=(1<<j);
//		}
//		h[i]=p;
//	}
//	for(int i=5500;i<=5530;++i) printf("%d ",h[i]);cout<<"\n";
} 
int st[300010][20];
inline void ST_work(){
	for(int i=1;i<=L;++i) st[i][0]=h[i];
	for(int i=1;i<=19;++i) for(int j=1;j+(1<<i)-1<=L;j++) st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
}
inline int ask_LCP(int l,int r){
	if(l==r) return 1e9;
	l++; 
	int k=log2(r-l+1);
	return min(st[l][k],st[r-(1<<k)+1][k]);
} 
long long ans=0;
inline int SAP(int l,int r){
	int u=rk[l];
	int p=u;
	for(int i=log2(u);i>=0;--i){
		if(p-(1<<i)<1) continue;
		if(ask_LCP(p-(1<<i),u)>=r-l+1) p-=(1<<i);
	}
	int q=u;
	for(int i=log2(L-u+1);i>=0;--i){
		if(q+(1<<i)>L) continue;
		if(ask_LCP(p,q+(1<<i))>=r-l+1) q+=(1<<i);
	}
	return q-p+1;
} 
signed main() {
	ios::sync_with_stdio(0);
// 	freopen("P3649_54.in","r",stdin);
	cin>>t;
	L=len=t.size();
	t=" "+t;
	s[++tot]='~';
	for(int i=1;i<=len;++i)
		s[++tot]=t[i],s[++tot]='~';
// 	for(int i=1;i<=len;++i) s3[i]=(s3[i-1]*131+t[i]-'a'+1)%1000000007;
	len=tot;
	power[0]=1;
	for(int i=1;i<=len;++i){
		power[i]=MOD(power[i-1]*131ll);
		s1[i]=MOD(s1[i-1]*131ll+s[i]-'a'+1);
	}
	for(int i=len;i>=1;--i)
		s2[i]=MOD(s2[i+1]*131ll+s[i]-'a'+1);
	for(int i=2;i<=len;++i){
		int p=0;
		for(int j=20;j>=0;--j){
			if(i-p-(1<<j)<=0 || i+p+(1<<j)>len) continue;
			if(gethash1(i-p-(1<<j),i+p+(1<<j))==gethash2(i-p-(1<<j),i+p+(1<<j))) p+=(1<<j);
		}
		if(p==0 && (i&1)) continue;
		int q=0;
		for(int j=20;j>=0;--j){
			if(q+(1<<j)>p) continue;
			if(mp.count(gethash1(i-q-(1<<j),i+q+(1<<j)))) q+=(1<<j);
		}
		q++;
		for(int j=p;j>=q;j-=2) MH.push_back({(i-j+1)/2,(i+j)/2}),mp.insert(gethash1(i-j,i+j)),mp.insert(gethash1(i-j-1,i+j+1));
	} 
	mp.clear();
	binary();
	height();
	ST_work();
	for(int i=0;i<MH.size();++i){
		int l=MH[i].first,r=MH[i].second;
		ans=max(ans,(long long)(r-l+1)*SAP(l,r));
	}
	cout<<ans;
	return 0;
}

就差几十毫秒了。

思路是用 Hash 找出所有本质不同的回文串,然后用 SA 暴力去匹配。

MLE 的方法找到了,现在主要是 TLE 了。

2024/8/27 11:05
加载中...