LibreOJ #2012. 「SCOI2016」背單詞
阿新 • • 發佈:2017-08-25
pan ring har cst target cstring n) color 插入
二次聯通門 : LibreOJ #2012. 「SCOI2016」背單詞
/* LibreOJ #2012. 「SCOI2016」背單詞 Trie + 貪心 大家都吐槽題目反人類 可我覺得還好,畢竟見的多了 不會做啊。。 正解好巧妙 考慮一下,發現一操作完全不必要,可以省去 因為所有的字符串的後綴關系會形成一個樹 那麽把字符串倒序插入Trie中 建樹,每次向子樹小的一個點轉移即可 */ #include <cstdio> #include <algorithm> #include<cstring> #define Max 100008 #define L 26 int N; char line[Max]; int trie[Max][L], T_C = 1; bool is[Max]; struct E { E *n; int to; }; E *list[Max], poor[Max], *Ta = poor; void Dfs (int now, int Father) { if (is[now]) { ++ Ta, Ta->to = now, Ta->n = list[Father], list[Father] = Ta; Father= now; } for (int i = 0; i < L; ++ i) if (trie[now][i]) Dfs (trie[now][i], Father); } int size[Max]; void Re_Dfs (int now) { size[now] = 1; for (E *e = list[now]; e; e = e->n) Re_Dfs (e->to), size[now] += size[e->to]; } int dfn[Max], top, C, Stack[Max], Answer; inlinebool Comp (int a, int b) { return size[a] < size[b]; } void Get_Answer (int now) { dfn[now] = ++ C; int pos = top + 1; for (E *e = list[now]; e; e = e->n) Stack[++ top] = e->to; if (top < pos) return ; std :: sort (Stack + pos, Stack + top + 1, Comp); for (int i = pos; i <= top; ++ i) Get_Answer (Stack[i]), Answer += dfn[Stack[i]] - dfn[now]; top = pos - 1; } int Main () { scanf ("%d", &N); register int i, j; int Id, x, now, Len; for (i = 1; i <= N; ++ i) { scanf ("%s", line); Len = strlen (line); for (j = Len - 1, now = 1; j >= 0; -- j) { Id = line[j] - ‘a‘; if (trie[now][Id] == 0) trie[now][Id] = ++ T_C; now = trie[now][Id]; } is[now] = true; } Dfs (1, 1), Re_Dfs (1), Get_Answer (1); printf ("%d", Answer); return 0; } int ZlycerQan = Main (); int main (int argc, char *argv[]) {;}
LibreOJ #2012. 「SCOI2016」背單詞