You are given n strings s1,s2,…,s, consisting of lowercase Latin letters. Let |x| be the length of string x.
Let a collapse C(a,b) of two strings a and b be the following operation:
- if a is empty, C(a,b)=b;
- if b is empty, C(a,b)=a;
- if the last letter of a is equal to the first letter of b, then C(a,b)=C(a1,|a|−1,b2,|b|), where sl,r is the substring of s from the l-th letter to the r-th one;
- otherwise, C(a,b)=a+b, i. e. the concatenation of two strings.
Calculate ∑i=1n∑j=1n|C(si,sj).
Input
The first line contains a single integer n (1≤n≤106).
Each of the next n lines contains a string si (1≤|si|≤106), consisting of lowercase Latin letters.
The total length of the strings doesn't exceed 106106.
Output
Print a single integer — ∑i=1n∑j=1n|C(si,sj)|
Examples
input
3
aba
ab
ba
output
Copy
20
input
Copy
5
abab
babx
xab
xba
bab
output
Copy
126
解析:
我们需要求的每个字符串对应的reverse,在进行字典树的建立,记录其它的 每个连续字字符串的 个数。
https://www.luogu.com.cn/problem/P1709
#include<bits/stdc++.h>
using namespace std;
const int N = int(1e6) +99;
int nxt;
int to[N][26];
int sum[N];
long long res;
void add(const string& s)
{
int v = 0;
++sum[v];//多少个 字符
for(auto c : s){
int i = c- 'a';
if(to[v][i] == -1){
to[v][i] = nxt++;
}
v = to[v][i];
++sum[v];
}
}
void upd(const string& s){
int curLen = s.size();
int v = 0;
for(auto c : s){
int i = c -'a';
if(to[v][i] == -1){ //没有找到这个字字符串
res+= sum[v]*1LL*curLen;//当前这一层的个数
break;
}else{
int nxtV = to[v][i];
res += (sum[v] - sum[nxtV]) * 1LL *curLen;
--curLen; //s字符串剩下的长度
v = nxtV;
}
}
}
void solve(int n,vector<string> v)
{
nxt = 1;
memset(sum,0,sizeof sum);
memset(to,-1,sizeof to);
for(int i = 0;i < n;i++){
add(v[i]);
}
for(int i = 0;i < n;i++)
{
reverse(v[i].begin(),v[i].end());
upd(v[i]);
}
}
int main(){
ios_base::sync_with_stdio(false);
int n;
cin >> n;
vector<string> v(n);
for(int i = 0;i < n;++i)
{
cin >> v[i];
reverse(v[i].end(),v[i].begin()); //反转字符串
}
solve(n,v);
cout << 2*res<<endl;
return 0;
}