P3804 【模板】后缀自动机
思路
很水的后缀自动机
找到最长的大小不为1的endpos与maxlen的乘积即可
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 1000100*2;
int trans[MAXN][26],suflink[MAXN],maxlen[MAXN],endpos[MAXN],ispre[MAXN],in[MAXN],n,cnt;
char s[MAXN];
int new_state(int _maxlen,int *_trans,int _suflink){
++cnt;
maxlen[cnt]=_maxlen;
if(_trans)
for(int i=0;i<26;i++)
trans[cnt][i]=_trans[i];
suflink[cnt]=_suflink;
return cnt;
}
int add_len(int u,int c){
int z=new_state(maxlen[u]+1,NULL,0);
ispre[z]=1;
while(u&&(!trans[u][c])){
trans[u][c]=z;
u=suflink[u];
}
if(!u){
suflink[z]=1;
return z;
}
int v= trans[u][c];
if(maxlen[v]==maxlen[u]+1){
suflink[z]=v;
return z;
}
int y=new_state(maxlen[u]+1,trans[v],suflink[v]);
suflink[v]=suflink[z]=y;
while(u&&trans[u][c]==v){
trans[u][c]=y;
u=suflink[u];
}
return z;
}
queue<int> q;
int main(){
scanf("%s",s+1);
n=strlen(s+1);
int pre=1;
cnt=1;
for(int i=1;i<=n;i++)
pre=add_len(pre,s[i]-'a');
for(int i=1;i<=cnt;i++)
in[suflink[i]]++;
for(int i=1;i<=cnt;i++)
if(!in[i])
q.push(i);
while(!q.empty()){
int x=q.front();
q.pop();
endpos[x]+=ispre[x];
endpos[suflink[x]]+=endpos[x];
in[suflink[x]]--;
if(!in[suflink[x]])
q.push(suflink[x]);
}
// for(int i=1;i<=cnt;i++)
// printf("%d %d!\n",endpos[i],maxlen[i]);
int ans=0;
for(int i=1;i<=cnt;i++)
if(endpos[i]>1)
ans=max(ans,endpos[i]*maxlen[i]);
printf("%d\n",ans);
return 0;
}