SAM板子,没什么好说的
建出来SAM然后跑个DFS统计答案就行了
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
#define N 3010
#define rint register int
#define il inline
#define idx(x) (x-'a'+1)
using namespace std;
//re
char str[N];
int head[N<<1];
int cte;
struct Edge{int to,nxt;}e[N<<1];
void ae(int u,int v){cte++;e[cte].to=v,e[cte].nxt=head[u],head[u]=cte;}
struct SAM{
int fa[N<<1],trs[N<<1][28],dep[N<<1],sum[N<<1],sz[N<<1],cnt,last;
void init(){cnt=last=1;}
void ins(int x)
{
int p=last,np=++cnt,q,nq;
last=np,dep[np]=dep[p]+1;
for(;p&&!trs[p][x];p=fa[p]) trs[p][x]=np;
if(!p){fa[np]=1;}
else{
q=trs[p][x];
if(dep[q]==dep[p]+1) fa[np]=q;
else{
fa[nq=++cnt]=fa[q];
fa[q]=fa[np]=nq;
dep[nq]=dep[p]+1;
memcpy(trs[nq],trs[q],sizeof(trs[q]));
for(;p&&trs[p][x]==q;p=fa[p]) trs[p][x]=nq;
}
}
}
ll dfs(int x)
{
ll ans=0;
for(int j=head[x];j;j=e[j].nxt){
int v=e[j].to;
ans=max(ans,dfs(v));
sz[x]+=sz[v],sum[x]+=sum[v];
}sz[x]++;
if(sz[x]==1) {sum[x]++;return 0;}
else {return max(ans,1ll*sum[x]*dep[x]);}
}
}sam;
int main()
{
freopen("testdata.in","r",stdin);
scanf("%s",str+1);
int len=strlen(str+1);
sam.init();
for(int i=len;i>=1;--i)
sam.ins(idx(str[i]));
for(int i=2;i<=sam.cnt;i++)
ae(sam.fa[i],i);
printf("%lld\n",sam.dfs(1));
return 0;
}