题意:
给你N个字符串,每个字符串可以缩写为他的前缀,但是必须保证所有串缩写后不重复,并且最后总长度最小。
题解:
先建立字典树,然后我们可以想到,在dfs的时候,如果当前节点本来没有串,那么他可以存他子树中某个串,我们用优先队列找到他子树的最长的节点,然后把这个节点代表的串用当前节点串代替,这样贪心即可。
但是对于每颗子树都要建立一个优先队列存他子树中所有的串长。对于这点我们可以用启发式合并来做。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <bitset>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <cmath>
#ifdef LOCAL
#define debug(x) cout<<#x<<" = "<<(x)<<endl;
#else
#define debug(x) 1;
#endif
#define chmax(x,y) x=max(x,y)
#define chmin(x,y) x=min(x,y)
#define lson id<<1,l,mid
#define rson id<<1|1,mid+1,r
#define lowbit(x) x&-x
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, int> pii;
const ll MOD = 1e9 + 7;
const double eps = 1e-10;
const int INF = 0x3f3f3f3f;
const ll INFLL = 0x3f3f3f3f3f3f3f3fll;
const int MAXN = 1e5 + 5;
priority_queue<int> q[MAXN];
struct nodes {
int nxt[26], v, dep;
} nd[MAXN];
int tot;
void add (char *s) {
int now = 0;
for (int i = 0; s[i]; i++) {
int id = s[i] - 'a';
if (!nd[now].nxt[id]) {
nd[now].nxt[id] = ++tot;
nd[tot].dep = i + 1;
}
now = nd[now].nxt[id];
}
nd[now].v = 1;
}
char s[MAXN];
int ans;
int tran[MAXN];
void dfs (int now) {
tran[now] = now;
for (int i = 0; i < 26; i++) {
int nxt = nd[now].nxt[i];
if (!nxt) continue;
dfs (nxt);
if(q[tran[now]].size() > q[tran[nxt]].size()) {
while(q[tran[nxt]].size()) q[tran[now]].push(q[tran[nxt]].top()), q[tran[nxt]].pop();
} else {
while(q[tran[now]].size()) q[tran[nxt]].push(q[tran[now]].top()), q[tran[now]].pop();
tran[now] = tran[nxt];
}
}
if (nd[now].v) {
ans += nd[now].dep;
q[tran[now]].push(nd[now].dep);
} else if (now) {
ans += nd[now].dep - q[tran[now]].top();
q[tran[now]].pop();
q[tran[now]].push(nd[now].dep);
}
}
int main() {
#ifdef LOCAL
freopen ("input.txt", "r", stdin);
#endif
int n;
scanf ("%d", &n);
for (int i = 1; i <= n; i++) {
scanf ("%s", s);
add (s);
}
dfs(0);
printf("%d\n", ans);
return 0;
}
后记:
不知道为什么,不用启发式也可以过,而且跑得还快一些。
但是我估计的复杂度是N^2logN。
启发式合并的话是NlogNlogN。