第五个点 MLE 了。
Trie 建字典树。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
string str[100100];
int s2[100100];
int cnt,siize[510010];
int s[510100][26],ans[100100],vis[510100];
int insert(string x,int yy){
int len=x.length(),now=0,ret=yy;
for(int i=1;i<=len;i++){
if(s[now][x[i-1]-'a']==0) s[now][x[i-1]-'a']=++cnt;
now=s[now][x[i-1]-'a'];
ret=min(ret,yy-vis[now]);
}
vis[now]=yy;
return ret;
}
void insert2(string x,int yy){
int len=x.length(),now=0;
for(int i=1;i<=len;i++){
if(s[now][x[i-1]-'a']==0) s[now][x[i-1]-'a']=++cnt;
now=s[now][x[i-1]-'a'];
}
vis[now]=yy;
}
void dfs(int p){
siize[p]=(vis[p]>0);
for(int i=0;i<26;i++) if(s[p][i]!=0){
dfs(s[p][i]);
siize[p]+=siize[s[p][i]];
}
}
struct node{
int x,num;
};
bool cmp(node aa,node bb){
if(aa.num==0) return false;
if(aa.num!=bb.num) return aa.num<bb.num;
return aa.x<bb.x;
}
int did(int p,int *f){
int f2[100001];
int cntt=0,cnttt=0;
for(int i=0;i<26;i++){
if(s[p][i]==0) continue;
if(vis[s[p][i]]) f[++cntt]=s[p][i];
else cnttt+=did(s[p][i],&f2[cnttt]);
}
for(int i=cntt+1;i<=cntt+cnttt;i++){
f[i]=f2[i-cntt];
}
return cntt+cnttt;
}
int cnt2=0;
void init(int p){
if(vis[p]) s2[++cnt2]=vis[p];
int nuum=26;
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > gt;
for(int i=0;i<26;i++){
if(s[p][i]==0){
nuum--;
continue;
}
if(vis[s[p][i]]==0){
nuum--;
int f[100001];
int len=did(s[p][i],&f[0]);
for(int i=1;i<=len;i++){
gt.push(make_pair(siize[f[i]],f[i]));
nuum++;
}
}
else{
gt.push(make_pair(siize[s[p][i]],s[p][i]));
}
}
while(!gt.empty()){
init(gt.top().second);
gt.pop();
}
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
cin>>str[i];
int len=str[i].length();
for(int j=1;j*2<=len;j++) swap(str[i][j-1],str[i][len-j]);
}
for(int i=1;i<=n;i++){
insert2(str[i],i);
}
dfs(0);
init(0);
for(int i=0;i<=510099;i++){
for(int j=0;j<26;j++) s[i][j]=0;
vis[i]=0;
}
cnt=0;
for(int i=1;i<=n;i++){
ans[i]=insert(str[s2[i]],i);
}
ll rans=0;
for(int i=1;i<=n;i++) rans+=ans[i];
cout<<rans;
return 0;
}