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;
}
posted @ 2026-09-21 22:10  lzx0921  阅读(6)  评论(0)    收藏  举报