SAM
直接看注释细节看这。
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,r,l) for(int i=(r);i>=(l);--i)
const int N=2e6+5;
int n,tot=1,la=1,lin[N],sz[N],len[N],t[N][26];
string s;
vector<int>ve[N];
void extend(int c){
int cur=++tot,p=la;// 新建节点
len[cur]=len[p]+1;// 长度 ++
la=cur;// 更新
sz[cur]=1;//由于任意两个不同的前缀的 endpos 等价类一定不同,于是考虑统计前缀的数量,这就等价于出现的次数了
while(!t[p][c]) t[p][c]=cur,p=lin[p];// 不断跳,全部更新一遍
if(!p) return lin[cur]=1,void();// 连到根
int q=t[p][c];// 存在
if(len[q]==len[p]+1) return lin[cur]=q,void();//符合
int qq=++tot;//新增
len[qq]=len[p]+1,lin[qq]=lin[q],lin[q]=lin[cur]=qq;
while(t[p][c]==q) t[p][c]=qq,p=lin[p];//更新
memcpy(t[qq],t[q],sizeof t[qq]);
}
ll dfs(int u){
ll res=0;
for(auto v:ve[u]){
res=max(res,dfs(v));
sz[u]+=sz[v];
if(sz[v]>1) res=max(res,sz[v]*1ll*len[v]);
}
return res;
}
void solve(){
cin>>s;
n=s.size();
for(char c:s) extend(c-'a');
rep(i,2,tot) ve[lin[i]].push_back(i);
cout<<dfs(1);
}
int main() {
cin.tie(0)->ios::sync_with_stdio(false);
solve();
return 0;
}

浙公网安备 33010602011771号