写了一个 n2 的假启发式合并也过了,跑的还比我 2logn 的快。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
int n,tot=1,K,L,P;
char c[50005];
int fa[100005];
int len[100005];
int mp[100005][2];
set <int> st[100005];
vector <int> g[100005];
inline int ins(int c,int las){
if(mp[las][c]){
int p=las,v=mp[p][c];
if(len[p]+1==len[v]) return v;
int x=++tot;
len[x]=len[p]+1;
for(int i:{0,1}) mp[x][i]=mp[v][i];
while(mp[p][c]==v) mp[p][c]=x,p=fa[p];
fa[x]=fa[v],fa[v]=x;
return x;
}
int x=++tot,p=las;
len[x]=len[p]+1;
while(p&&!mp[p][c]) mp[p][c]=x,p=fa[p];
if(!p) fa[x]=1;
else{
int v=mp[p][c];
if(len[p]+1==len[v]) fa[x]=v;
else{
int y=++tot;
len[y]=len[p]+1;
for(int i:{0,1}) mp[y][i]=mp[v][i];
while(mp[p][c]==v) mp[p][c]=y,p=fa[p];
fa[y]=fa[v],fa[x]=fa[v]=y;
}
}
return x;
}
inline void in(int &n){
n=0;
char c=getchar();
while(c<'0' || c>'9') c=getchar();
while(c>='0'&&c<='9') n=n*10+c-'0',c=getchar();
return ;
}
inline void solve(int u){
for(int v:g[u]){
solve(v);
if(st[u].size()>st[v].size()) swap(st[u],st[v]);
for(int v:st[v]) st[u].insert(v);
}
// printf("%d:%d\n",u,st[u].size());
if(st[u].size()<2) return ;
auto it=st[u].begin();
int mn=1e9,pos=0;
while(it!=st[u].end()){
if(it!=st[u].begin()){
int x=*it-*prev(it);
if(x<mn) mn=x,pos=*prev(it);
}
if(next(it)!=st[u].end()){
int x=*next(it)-*it;
if(x<mn) mn=x,pos=*it;
}
it++;
}
if(K<len[u]/mn+1){
K=len[u]/mn+1;
L=mn;
P=pos-len[u]+1;
}
return ;
}
int main(){
in(n);
for(int i=1;i<=n;i++){
char ch[3];
scanf("%s",ch+1);
c[i]=ch[1];
}
int las=1;
for(int i=1;i<=n;i++) las=ins(c[i]-'a',las),st[las].insert(i);
for(int i=2;i<=tot;i++) g[fa[i]].emplace_back(i);
solve(1);
printf("%d\n%d\n%d\n",K,L,P);
return 0;
}