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; }