cunzai_zsy0531

关注我

P3804 [模板]后缀自动机 题解

题面

拆出来的点贡献为 \(0\),其他贡献为 \(1\),在 DAWG 上统计一个后缀和即可。

点击查看代码
const int N=1e6+13,M=26;
int n,len[N<<1],nxt[N<<1],ptot=1,lastpos=1,ind[N<<1];
ll cnt[N<<1];
std::array<int,M> son[N<<1],boom;
char s[N];
inline int newpos(std::array<int,M> nson,int nlen){return ++ptot,len[ptot]=nlen,swap(son[ptot],nson),ptot;}
inline void insert(int c){
	int p=lastpos;int u=newpos(boom,len[p]+1);cnt[u]=1;
	while(p&&!son[p][c]) son[p][c]=u,p=nxt[p];
	if(!p) return lastpos=u,nxt[u]=1,void();
	int d=son[p][c];
	if(len[d]==len[p]+1) nxt[u]=d;
	else{
		int v=newpos(son[d],len[p]+1);
		nxt[v]=nxt[d],nxt[d]=v,nxt[u]=v;
		while(p&&son[p][c]==d) son[p][c]=v,p=nxt[p];
	}
	lastpos=u;
}
int main(){
#ifdef LOCAL
	freopen("P3804_4.in","r",stdin);
#endif
	read(s+1);n=strlen(s+1);
	for(int i=1;i<=n;++i) insert(s[i]-'a');
	for(int i=2;i<=ptot;++i) ind[nxt[i]]++;
	std::queue<int> q;
	for(int i=2;i<=ptot;++i)
		if(!ind[i]) q.push(i);
	while(!q.empty()){
		int u=q.front();q.pop();
		if(nxt[u]==1) continue;
		cnt[nxt[u]]+=cnt[u];
		if(!(--ind[nxt[u]])) q.push(nxt[u]);
	}
	ll ans=0;
	for(int i=2;i<=ptot;++i)
		if(cnt[i]>1) ans=max(ans,cnt[i]*len[i]);
	println(ans);
	return 0;
}
posted @ 2022-05-18 20:41  cunzai_zsy0531  阅读(14)  评论(0编辑  收藏  举报