考场上看到后缀两个字就逃了
实际上并不需要后缀数组之类的高级知识
后缀反转即是前缀
反转,建trie
,贪心
因为发现规则一需要被避免,规则二可以合并至规则三
对于规则三
重新建树,每个串连向其后缀
然后就可以DFS了
数组开小了也会MLE???
#include<bits/stdc++.h>
using namespace std;
#define in Read()
int in{
int i=0,f=1;char ch=0;
while(!isdigit(ch)&&ch!='-') ch=getchar();
if(ch=='-') ch=getchar(),f=-1;
while(isdigit(ch)) i=(i<<1)+(i<<3)+ch-48,ch=getchar();
return i*f;
}
const int N=1e6+5,M=2e6;
int n,trie[M][26],val[N],sz,siz[N],cnt,dfn[N];
long long ans;
char s[M];
vector<int>G[N];
void insert(char *t,int id,int len){
int p=0;
for(int i=0;i<len;++i){
int c=t[i]-'a';
if(!trie[p][c]) trie[p][c]=++sz;
p=trie[p][c];
}
val[p]=id;
return;
}
void DFS1(int p,int t){
for(int q,i=0;i<26;++i){
if(q=trie[p][i]){
if(val[q]){
G[val[t]].push_back(val[q]);
DFS1(q,q);
}else DFS1(q,t);
}
}
return;
}
bool cmp(const int &u,const int &v){
return siz[u]<siz[v];
}
void DFS2(int u){
siz[u]=1;
for(int e=0;e<G[u].size();++e){
int v=G[u][e];
DFS2(v);
siz[u]+=siz[v];
}
sort(G[u].begin(),G[u].end(),cmp);
return;
}
void DFS3(int u){
dfn[u]=cnt++;
for(int e=0;e<G[u].size();++e){
int v=G[u][e];
ans+=cnt-dfn[u];
DFS3(v);
}
return;
}
int main(){
n=in;
for(int i=1;i<=n;++i){
scanf("%s",s);
int len=strlen(s);
reverse(s,s+len);
insert(s,i,len);
}
DFS1(0,0);
DFS2(0);
DFS3(0);
printf("%lld\n",ans);
return 0;
}