字符串“wyhaksx”和“wyhaknoi” w y h a k s x w y h a k n o i 此时 wyhak 这个缩写是有歧义的,因为它两句话都能表示,而且它还是最长有歧义缩写; 但是再加一个字母,wyhaks 就没有歧义了,是最短无歧义缩写, 因为它只能表示 wyhaksx 不能表示 wyhaknoi,而你找不到比它更短的了
std::stringfind(int down){ int endNode = findNode(down); // 调用上面的函数获取最终节点 std::string res = ""; std::string &ds = originalStrings[down]; int now = 1; for (int i = 0, len = (int) ds.length(); i < len; ++i) { int next = node[now].next[toNum(ds[i])]; // 获取当前节点的子节点 res += ds[i]; now = next; // 复制字符串,更新位置 if (next == endNode) break; // 如果下一个节点是终点,那就停掉 } return res; // 返回这个输出的结果就好了 }
structNode { bool str; int from, siz, edges; int next[30]; Node() { str = 0; from = siz = edges = 0; memset(next, 0, sizeof next); } }; Node node[MAXNODES]; int cnt;
inttoNum(constchar &s){ if (s == '#') return27; return s - 'a' + 1; }
public: Trie() { cnt = 1; }
voidinsert(std::string s, int down){ int now = 1, strLen = (int) s.length(); for (int i = 0; i < strLen; ++i) { int &next = node[now].next[toNum(s[i])]; if (next == 0) { next = ++cnt; node[next].from = now; ++node[now].edges; } now = next; } node[now].str = true; location[down] = now; } intfindNode(int down){ // 沿着叶子节点往上走,找到第一个分叉节点,返回它的儿子 // 分叉节点即为向下连的边超过两条的点 int now = location[down]; while (true) { if (now == 1) break; // md 居然滚回根节点了 int father = node[now].from; // 父亲节点 // printf("\tNow on node [%d], its father is [%d], \n\tits father's out-edges amount is %d;\n", now, father, node[father].edges); if (node[father].edges >= 2) break; // 找到了 orz now = father; // 往上跳 } return now; } std::stringfind(int down){ // 获得答案 // printf("[DEBUG] Now processing [%d] -> %s:\n", down, originalStrings[down].c_str()); int endNode = findNode(down); // printf("\tendNode = %d\n", endNode); // printf("\tCopying string...\n"); std::string res = ""; std::string &ds = originalStrings[down]; int now = 1; for (int i = 0, len = (int) ds.length(); i < len; ++i) { int next = node[now].next[toNum(ds[i])]; // printf("\tnow = %d, next = %d, now char = %c\n", now, next, ds[i]); res += ds[i]; now = next; if (next == endNode) break; } return res; } } trie;
intmain(){ int n = 0; while (std::cin >> originalStrings[++n]); --n; for (int i = 1; i <= n; ++i) trie.insert(originalStrings[i] + "#", i); // trie.initSize(); for (int i = 1; i <= n; ++i) { printf("%s %s\n", originalStrings[i].c_str(), trie.find(i).c_str()); } return0; }