思路:可以用map来替代字典树。对于一个字符串s来说,它的贡献只和它前缀有关,
所以对于每个字符串我们遍历它的前缀。但由于长前缀对短前缀也有贡献,比如
对于字符串abcd,它既影响了abcd,也影响了abc,ab,a,若直接对每个前缀
取和会有重复的贡献,所以需要减去重复的贡献。设abc的贡献为v["abc"],容易
得abc去除abcd的重复贡献为v["abc"]-v["abcd"]。
但直接用<string,int>哈希会re,所以对string哈希成unsigned long long类型
就可以过了.。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=3e6+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
map<ull,ull> v;
ull t[N],tt[N];
void solve(){
int n;cin>>n;
ull ans=0,cnt;
for(int i=1;i<=n;i++){
string s;cin>>s;
cnt=0;
ull x=1;
ull l=s.size();
for(int j=0;j<l;j++){
x=x*131+s[j]-'a';
t[++cnt]=x;
}
ull last=0;
for(int j=cnt,k=0;j>=1;j--,k++){
ull y=t[j];
ans+=(v[y]-last)*(l-k);
last=v[y];
}
for(int j=1;j<=cnt;j++){
ull y=t[j];
v[y]++;
}
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t=1;
// cin>>t;
while(t--){
solve();
}
}