//lg 3804
//Copyright yeyou26
//注意:这道题不是纯纯的后缀自动机,main函数有一点额外处理
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N (int(2e6+6))
int fa[N];
int ch[N][28];
int len[N];
int cnt[N];
ll ans;
int idx=1;
int np=1;
string s;
vector<int> e[N];
void init();
void Addsam(int c);
ll calculate();
void dfs(int u);
int main()
{
freopen("working.in","r",stdin);
freopen("working.out","w",stdout);
init();
for(int i=0;s[i];i++)
{
Addsam(s[i]&31);
}
for(int i=2;i<=idx;i++)
{
e[fa[i]].push_back(i);
}
dfs(1);
cout<<ans;
return 0;
}
//Function Implementation
void dfs(int u)
{
for(int v : e[u])
{
dfs(v);
cnt[u]+=cnt[v];
}
if(cnt[u]>1) ans=max(ans,(ll)cnt[u]*len[u]);
}
void Addsam(int c)
{
//p回跳指针 np新节点 q链接点 nq分裂链接点
int p=np,np=++idx;
len[np]=len[p]+1;
cnt[np]=1;
for(;p && !ch[p][c];p=fa[p]) ch[p][c]=np;
//case 1 找不到任何出现过(新串后缀)
if(p==0) fa[np]=1;
else
{
int q=ch[p][c];
//case 2 链接点合法,直接连
if(len[q]==len[p]+1) fa[np]=q;
else
{
//case 3 链接点不合法,裂开为nq和q,q负责长度大于len(p)+1的串,nq负责长度小于等于len(p)+1的串
int nq=++idx;
len[nq]=len[p]+1;
fa[nq]=fa[q];fa[q]=nq;fa[np]=nq;
//指向q的转移边指向nq
for(;p && ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
//从q出发的转移边丢给nq一份
memcpy(ch[nq],ch[q],sizeof(ch[q]));
}
}
}
void init()
{
cin>>s;
}
标签:ch,SAM,fa,后缀,len,int,np,nq,自动机
From: https://www.cnblogs.com/yeyou26/p/17990712