【网易有道面试题一】求单词集可以唯一标识每个单词的最短前缀

这道题的给定一个单词集合,里面没有重复的单词,然后为每一个单词求出可以唯一标识这个单词的最短前缀.

比如对于单词集合:

输入:{abc, abcd}, 输出就是abc, abcd

输入:{a, c}, 输出就是a, c

输入:{abc, abd, abcd}, 输出就是abc, abd, abcd

输入:{abc, bdc}, 输出就是 a, b

 

为了节省空间和提高运算速度,字典树是一个非常好的选择,而且往往和前缀相关的问题都可以用字典树来解决.

 

#include <iostream> #include <string> #define MAX_N 100000 //字典树的空间大小 #define MAX_W 1000 //单词的个数上线 #define MAX_L 26 //字典树子树的个数 using namespace std; //字典树的定义 struct trie { int w_index; //某个单词插入的时候经过这个结点就将w_index设置为这个单词的编号 int tag; //0:普通结点, 1: 一个单词的末尾结点 int next[MAX_L + 1]; //子树 }tries[MAX_N]; //单词的定义 struct word { int subPos; string w; }words[MAX_W]; int tIndex; //指示字典树空间中当前可用空间的下标起始范围 int wNum; //单词个数 //向字典树中插入单词str, index标识当前单词的标号 void insert(const string &str, int windex) { int curPos = 0; //扫描单词的每一位 for(int p = 0; p < str.length(); p++) { //当前字母 int tempPos = str[p] - 'a' + 1; //当前结点尚未被访问,则建立当前子树 if(tries[curPos].next[tempPos] == 0) { tries[curPos].next[tempPos] = ++tIndex; curPos = tIndex; //对当前节点标识当前单词的编号,由于这个结点尚未被访问过,因此这个结点到词首的前缀完全可以标识这个单词 tries[curPos].w_index = windex; //标识结点的类型,0普通结点,1某个单词的末尾结点,由于末尾结点不可以被其他单词抹掉,因此需要单独标识 if(p == str.length() - 1) tries[curPos].tag = 1; else tries[curPos].tag = 0; } //当前结点已经被之前的单词访问过了 else { curPos = tries[curPos].next[tempPos]; //普通结点,不是某个单词的末尾结点,则将w_index设置为-1,表示这个结点对于标识单词不足够 if(tries[curPos].tag != 1) tries[curPos].w_index = -1; //当前单词的末尾结点,由于这个路径已经被别的单词访问过了,所以只能在这最后一位标识当前单词了 if(p == str.length() - 1) { tries[curPos].w_index = windex; tries[curPos].tag = 1; } } } } //dfs遍历,寻找每个单词的最短唯一前缀,先找到的某个结点的w_index不为-1就表示当前遍历 //得到的前缀是可以标识第w_index单词的最短前缀 void travel(int len, int curIndex) { if(curIndex != 0 && tries[curIndex].w_index != -1) { words[tries[curIndex].w_index].subPos = len; if(tries[curIndex].tag != 1) return; } for(int i = 1; i <= MAX_L; i++) { if(tries[curIndex].next[i] != 0) travel(len + 1, tries[curIndex].next[i]); } } int main() { tIndex = 0; string temp; memset(tries, 0, sizeof(tries)); cin>>wNum; for(int i = 0; i < wNum; i++) { cin>>words[i].w; insert(words[i].w, i); } travel(0, 0); for(int j = 0; j < wNum; j++) { cout<<words[j].w<<" "<<words[j].w.substr(0, words[j].subPos)<<endl; } return 0; } 

你可能感兴趣的:(c,面试,struct,String,insert,网易)