参考: 不同子串个数
用d[i]
来表示该状态点是否为终止点,最后利用每个点的后缀链接形成一棵树,每个点所表示的最长字符串都是其子树中各节点的最长公共后缀。
// Created by CAD
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e6+5;
struct state{
int len,link;
vector<int> Next;
state(){Next.resize(26);}
}st[maxn<<1];
int siz=0,last=0;
void init(){
st[0].len=0;
st[0].link=-1;
}
int d[maxn<<1];
void extend(int c){
int cur=++siz;
d[cur]=1;
st[cur].len=st[last].len+1;
int p=last;
while(~p&&!st[p].Next[c]){
st[p].Next[c]=cur;
p=st[p].link;
}
if(p==-1) st[cur].link=0;
else{
int q=st[p].Next[c];
if(st[p].len+1==st[q].len) st[cur].link=q;
else{
int clone=++siz;
st[clone].len=st[p].len+1;
st[clone].Next=st[q].Next;
st[clone].link=st[q].link;
while(~p && st[p].Next[c]==q){
st[p].Next[c]=clone;
p=st[p].link;
}
st[q].link=st[cur].link=clone;
}
}
last=cur;
}
int ans;
vector<int> g[maxn<<1];
void dfs(int u){
for(auto i:g[u]){
dfs(i);
d[u]+=d[i];
}
if(d[u]!=1) ans=max(ans,d[u]*st[u].len);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
init();
string s;cin>>s;
for(auto i:s)
extend(i-'a');
for(int i=1;i<=siz;++i)
g[st[i].link].push_back(i);
dfs(0);
cout<<ans<<endl;
return 0;
}