求∑0<i<n∑i<j≤nlcp(si,sj)
建立Trie树暴力跑一下,点上用组合数计算结果
#include <iostream>
#include <sstream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <map>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef class TrieNode {
public:
map<int, TrieNode*> next;
int val;
int ends;
TrieNode():val(0), ends(0) {
}
}TrieNode;
#define lim 1000005
TrieNode pool[lim];
TrieNode* top = pool;
inline TrieNode* newnode() {
return top++;
}
typedef class Trie {
public:
TrieNode* root;
Trie():root(newnode()) {}
inline void insert(char *str) {
TrieNode* p = root;
for(char *ch = str; *ch; ch++) {
int c = *ch - 'a';
p->val++;
if(!p->next[c])
p->next[c] = newnode();
p = p->next[c];
}
p->val++;
p->ends++;
}
}Trie;
long long res = 0;
typedef map<int, TrieNode*>::iterator mii;
void getRes(TrieNode*& node, int len) {
for(mii i = node->next.begin(); i != node->next.end(); i++)
for(mii j = i; j != node->next.end(); j++)
if(j != i)
res += i->second->val * 1LL * j->second->val * len;
for(mii i = node->next.begin(); i != node->next.end(); i++)
getRes(i->second, len + 1);
if(node->ends)
res += (node->val - node->ends) * 1LL * node->ends * len,
res += node->ends * 1LL * (node->ends - 1) / 2 * len;
}
int n;
char buf[lim];
Trie trie;
inline void init() {
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%s", buf), trie.insert(buf);
}
inline void solve() {
getRes(trie.root, 0);
printf(Auto, res);
}
int main() {
init();
solve();
return 0;
}