109 后缀自动机(SAM)
视频链接:
P3804 【模板】后缀自动机 (SAM)。
// Luogu P3804 【模板】后缀自动机 (SAM) #include#include #include using namespace std; typedef long long LL; const int N=2e6+10; int h[N], e[N], ne[N], idx; char str[N]; LL cnt[N], ans; int tot=1, cur=1; int len[N], fa[N], ch[N][26]; void extend(int c){ // p指针,cur当前点,q链接点,nq新链接点 int p = cur; cur = ++tot; len[cur]=len[p]+1; cnt[cur]=1; for(; p&&!ch[p][c]; p=fa[p]) ch[p][c]=cur; if(p==0) fa[cur]=1;//1.c是新字符 else{ int q=ch[p][c]; if(len[q]==len[p]+1)fa[cur]=q;//2.有链接点 else{ //3.无链接点 int nq = ++tot; //新建链接点 len[nq]=len[p]+1; fa[nq]=fa[q]; fa[q]=nq; fa[cur]=nq; memcpy(ch[nq],ch[q],sizeof(ch[q])); for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq; } } } void add(int a, int b){ e[++idx]=b, ne[idx]=h[a], h[a]=idx; } void dfs(int u){ for(int i=h[u]; i; i=ne[i]){ dfs(e[i]); cnt[u] += cnt[e[i]]; } if(cnt[u]>1) ans=max(ans, cnt[u]*len[u]); } int main(){ scanf("%s", str); for(int i=0;str[i];i++) extend(str[i]-'a'); for(int i=2; i<=tot; i++) add(fa[i], i); dfs(1); printf("%lld\n", ans); return 0; }