#include<bits/stdc++.h>
using namespace std;
const int M=2e6+5;
struct node{
int ch[26];
int len,fa;
node(){memset(ch,0,sizeof(ch));len=0;}
}dian[M];
vector<int> G[M];
int las=1,tot=1;//指向一个空状态
long long sum[M],ans;
void add(int c){
int p=las;
int np=las=++tot;//更新last的值
sum[tot]=1;
dian[np].len=dian[p].len+1;
for(;p&&!dian[p].ch[c];p=dian[p].fa){//如果它没有字符c的转移,那就添加字符c的转移,指向np,然后走向其后缀链接,直到已有字符c的转移,就停止。
dian[p].ch[c]=np;
}
if(!p) dian[np].fa=1;//来到了空状态
else {
int q=dian[p].ch[c];
if(dian[q].len==dian[p].len+1) {
dian[np].fa=q;
}
else {
int nq=++tot;//新建一个q的复制状态
dian[nq]=dian[q];
dian[nq].len=dian[p].len+1;
dian[q].fa=dian[np].fa=nq;//将np的后缀链接指向nq,并将q的后缀链接重定向到nq
for(;p&&dian[p].ch[c]==q;p=dian[p].fa){//从p开始沿着后缀链接走,对每个状态我们都检查是否有指向q的,字符c的转移。
dian[p].ch[c]=nq;//将其重定向至nq
}
}
}
}
char s[M];int _len;
void dfs(int x){
int siz=G[x].size();
for(int i=0;i<siz;i++){
int y=G[x][i];
dfs(y);
sum[x]+=sum[y];
}
if(sum[x]!=1) ans=max(ans,1LL*dian[x].len*sum[x]);
}
int main(){
scanf("%s",s);
_len=strlen(s);
for(int i=0;i<_len;i++) add(s[i]-'a');
for(int i=2;i<=tot;i++){//逐个加入字符
G[dian[i].fa].push_back(i);
}
dfs(1);
printf("%lld",ans);
return 0;
}
【模板】后缀自动机SAM
最新推荐文章于 2022-09-01 20:10:41 发布