题解 虚空恶魔

传送门

考试的时候以为切入点应该是在sam上维护不相交子串,于是不会做
写了个暴力还忘删调试了

其实这题只需要找到两个不相交的相同子串
维护出endpos集合中的最小值和最大值就可以了

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2000010
#define ll long long
//#define int long long

int n;
ll ans;
char s[N];
int len[N<<1], fail[N<<1], tr[N<<1][26], lft[N<<1], rit[N<<1], now, tot;
void init() {now=tot=0; memset(lft, 127, sizeof(lft)); for (int i=0; i<26; ++i) tr[0][i]=0; fail[0]=-1;}
void insert(char c, int pos) {
	c-='a';
	int cur=++tot;
	for (int i=0; i<26; ++i) tr[cur][i]=0;
	len[cur]=len[now]+1;
	int p, q;
	for (p=now; ~p&&!tr[p][c]; tr[p][c]=cur,p=fail[p]);
	if (p==-1) fail[cur]=0;
	else if (len[q=tr[p][c]]==len[p]+1) fail[cur]=q;
	else {
		int cln=++tot;
		len[cln]=len[p]+1;
		fail[cln]=fail[q];
		for (int i=0; i<26; ++i) tr[cln][i]=tr[q][i];
		for (; ~p&&tr[p][c]==q; tr[p][c]=cln,p=fail[p]);
		fail[cur]=fail[q]=cln;
	}
	now=cur;
	lft[cur]=rit[cur]=pos;
}

namespace force{
	void solve() {
		init();
		insert(s[1], 1);
		for (int i=2; i<=n; ++i) {
			// cout<<"i: "<<i<<endl;
			for (int j=i,u=0,l=0; j<=n; ++j) {
				while (~u&&!tr[u][s[j]-'a']) u=fail[u], l=len[u];
				if (u==-1) u=l=0;
				else u=tr[u][s[j]-'a'], ans=max(ans, 1ll*(i-1)*(++l));
			}
			insert(s[i], i);
		}
		reverse(s+1, s+n+1);
		init();
		insert(s[1], 1);
		for (int i=2; i<=n; ++i) {
			// cout<<"i: "<<i<<endl;
			for (int j=i,u=0,l=0; j<=n; ++j) {
				while (~u&&!tr[u][s[j]-'a']) u=fail[u], l=len[u];
				if (u==-1) u=l=0;
				else u=tr[u][s[j]-'a'], ans=max(ans, 1ll*(i-1)*(++l));
			}
			insert(s[i], i);
		}
		printf("%lld\n", ans);
		exit(0);
	}
}

namespace task{
	int deg[N<<1], tem[N<<1];
	void solve() {
		init();
		for (int i=1; i<=n; ++i) insert(s[i], i);
		for (int i=1; i<=tot; ++i) ++deg[len[i]];
		for (int i=1; i<=tot; ++i) deg[i]+=deg[i-1];
		for (int i=1; i<=tot; ++i) tem[deg[len[i]]--]=i;
		for (int i=tot,t; i; --i) {
			t=tem[i];
			lft[fail[t]]=min(lft[fail[t]], lft[t]);
			rit[fail[t]]=max(rit[fail[t]], rit[t]);
			if (lft[t]<=rit[t]-len[t]) ans=max(ans, max(1ll*(rit[t]-len[t])*len[t], 1ll*len[t]*(n-lft[t])));
		}
		printf("%lld\n", ans);
		exit(0);
	}
}

signed main()
{
	scanf("%s", s+1);
	n=strlen(s+1);
	// force::solve();
	task::solve();
	
	return 0;
}
posted @ 2021-12-13 20:26  Administrator-09  阅读(1)  评论(0编辑  收藏  举报