今天做了两道水题,要多水有多水...
其中有一道题是这样子的:
(6) 已知手机按键上数目到字母的映射:( 除了 "Q" 和 "Z")

给你一份dict.txt,然后给你一串数字(长度最长为12),要求你从dict.txt中找出匹配的字符串.如,给出4734,则dict.txt中与之匹配的只有GREG.
[解] 看完题目我是吓到了.因为我以为这道题的数据规模会是很大,虽然3^12≈5*10^5不算是很大,但是如果测试数据有很多组的话,应该还是会TLE的.既然这样,那就只得对dict.txt建字典树了吧..对于这道题来说,建树过程是很容易的,每个节点有26个子节点,顺着字符串一路建下去就OK了.但是,有点麻烦的是,对输入的一串数字,如何查找出与之匹配的所有字符串.一般的字典树查找的确定性是明显的,存在就是存在,不存在就不存在.而这题中,根据映射关系,一个数字是对应于3个字母的,因此实际上的查找需要用到搜索,对于每一数字,遍历它的3种可能..我写字典树时就卡在这里了,然后很无聊的想了下,这么做实际上复杂度就变成了1+3^1+3^2+...+3^len=3^(len+1),而一般的字典树的复杂度为O(len),因此其实还不如暴力来得快...在一筹莫展的时候,突然发现漏读了题目的数据规模了,测试数据竟然只有一个,于是直接将dict.txt中每一行字符串转为数字串看是否与目标相同就行了..大汗..
迅速秒完水题,觉得写了不短时间的字典树代码不能浪费了,于是修改了下,部分代码贴在下面:
#define max_num 26
struct node
{
bool is_word ; // 根到该节点是否对应一个字符串
node *next[max_num];
node()
{
is_word = false;
for(int i = 0;inext[str[i]-'a'] == NULL)
return false;
location = location->next[str[i]-'a'];
}
return location->is_word;
};
void insert(const string str) //插入
{
if(root == NULL)
root = new node;
node *location = root;
for(int i = 0;inext[site] == NULL)
{
location->next[site] = new node;
location = location->next[site];
}
else
location = location->next[site];
}
location->is_word = true;
};
bool del(const string str) //删除
{
node *location = root;
for(int i = 0;inext[str[i]-'a'] == NULL)
return false;
location = location->next[str[i]-'a'];
}
if(location->is_word)
location->is_word = false;
else
return false;
return true;
}
};
PS: 短发的小德把长发的纳豆横扫了,看来以后都留不了长发了..