POJ 2001 Shortest Prefixes(字典树)
题目链接:http://poj.org/problem?id=2001
题意:找每一个单词能够区分自己与其它单词的最短的前缀。
思路:裸的字典树。每一个节点多存一下到该节点为前缀的有几颗子树。
代码:
#include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> #include <string> #include <vector> #include <map> using namespace std; #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 #define ceil(x, y) (((x) + (y) - 1) / (y)) const int SIZE = 35; const int N = 2e5 + 10; const int INF = 0x7f7f7f7f; const int MAX_WORD = 25; struct Trie { int val[SIZE]; int c; }; int sz, n; Trie pn[N]; char str[N][MAX_WORD]; int newnode() { memset(pn[sz].val, 0, sizeof(pn[sz].val)); pn[sz].c = 0; return sz++; } void init() { n = sz = 0; newnode(); } void insert(char *s) { int u = 0; for (int i = 0; s[i]; i++) { int idx = s[i] - 'a'; if (!pn[u].val[idx]) pn[u].val[idx] = newnode(); u = pn[u].val[idx]; pn[u].c++; } } int findstr(char *s) { int u = 0; for (int i = 0; s[i]; i++) { int idx = s[i] - 'a'; if (pn[u].c == 1) return i - 1; if (!pn[u].val[idx]) return i; u = pn[u].val[idx]; } return strlen(s) - 1; } int main() { init(); while (scanf("%s", str[n]) != EOF) insert(str[n++]); for (int i = 0; i < n; i++) { printf("%s ", str[i]); int k = findstr(str[i]); for (int j = 0; j <= k; j++) printf("%c", str[i][j]); printf("\n"); } return 0; }