题目
每一类串出现的次数就是以该类为根的子树中是前缀节点的(差不多为叶子节点 有不同)个数。 这类串在fail树上往下一直走,直到没路,走到的一定是前缀节点,然后所有以该类串为后缀的前缀节点都会被他走到。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define m(a,b) memset(a,b,sizeof a)
using namespace std;
const int N=1e6+5;
struct Edge{int to,nex;}edge[N<<1];
int head[N<<1],tvt;
void add(int from,int to){
edge[++tvt]=(Edge){to,head[from]};head[from]=tvt;
}
struct node{
int len,fa,ch[26];
node(){len=fa=0;m(ch,0);}
}d[N<<1];
int las=1,tot=1;
char s[N];int sz[N<<1];
void update(int c){
int p=las,np=las=++tot;sz[tot]=1;
d[np].len=d[p].len+1;
for(;p&&!d[p].ch[c];p=d[p].fa) d[p].ch[c]=np;
if(!p) d[np].fa=1;
else{
int q=d[p].ch[c];
if(d[q].len==d[p].len+1) d[np].fa=q;
else{
int nq=++tot;d[nq]=d[q];
d[nq].len=d[p].len+1;
d[q].fa=d[np].fa=nq;
for(;p&&d[p].ch[c]==q;p=d[p].fa) d[p].ch[c]=nq;
}
}
}
int ans;
void dfs(int x){
for(int i=head[x];i;i=edge[i].nex){
int y=edge[i].to;
dfs(y),sz[x]+=sz[y];
}
if(sz[x]!=1) ans=max(ans,sz[x]*d[x].len);
}
int main(){
scanf("%s",s+1);int len=strlen(s+1);
for(int i=1;i<=len;++i) update(s[i]-'a');
for(int i=2;i<=tot;++i) add(d[i].fa,i);
dfs(1);
printf("%d\n",ans);
}