http://codeforces.com/contest/965/problem/E
题意:给出N个字符串,保证字符串总长度<=1e5, 对于每个单词找到他的一个非空前缀代表他, 并且需要保证找的N个前缀不能有相同的,且前缀总长度最小。
题解:很容易想到字典树,那么就是在字典树上找N个节点,我们利用记忆化,并且启发式合并一个节点的子树, 然后即可。具体看代码。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 100007;
int ch[maxn][26], root, tot;
bool ed[maxn];
char s[maxn];
multiset<int> c[maxn];
void dfs(int u, int d)
{
for(int i = 0;i < 26;i ++) {
if(ch[u][i]) {
dfs(ch[u][i], d + 1);
for(auto it : c[ch[u][i]]) c[u].insert(it);
}
}
if(ed[u]) {
c[u].insert(d);
} else if(d != 0) {
c[u].erase(prev(c[u].end()));
c[u].insert(d);
}
}
int main()
{
auto add = [&] () ->void {
int len = strlen(s);
int now = root;
for(int i = 0;i < len;i ++) {
int key = s[i] - 'a';
if(!ch[now][key]) ch[now][key] = ++tot;
now = ch[now][key];
}
ed[now] = 1;
};
int n;
scanf("%d", &n);
for(int i = 1;i <= n;i ++) {
scanf("%s", s);
add();
}
dfs(0, 0);
int sum = accumulate(c[0].begin(),c[0].end(), 0);
printf("%d\n", sum);
return 0;
}