求单词最短的确切前缀表示

是今天看到CareerCup上的问题:

Use the shorest unique prefix to represent each word in the array 
input: ["zebra", "dog", "duck",”dot”] 
output: {zebra: z, dog: do, duck: du} 
input: [bearcat, bear] 
output: {bearcat: bearc, bear: ""}

大意即,给出一系列单词,然后求每个单词的最短前缀表示,使得每个前缀表示都能唯一确定整个单词,第二个输入输出表明当单词的所有前缀都不能唯一地代表这个单词时,其前缀表示为空。

思路即将所有单词插入Trie中,然后找到第一个出现频率为1的前缀即可。

#include <cstring>
#include <exception>
#include <iostream>
#include <string>
using namespace std;

class WordNotFoundException : public exception{
private:
	string description;
public:
	WordNotFoundException(const string& word) : description(word + " not found"){}
	~WordNotFoundException() throw() {}
	virtual const char* what()const throw() {
		return description.c_str();
	}
};

class WordTrie{
private:
	static const int MAX = 26;
	struct TrieNode{
		int freq;
		bool eow;
		TrieNode* ch[MAX];
	};
	TrieNode* root;
private:
	bool isLeaf(const TrieNode* p)const{
		for(int i = 0; i < MAX; ++i){
			if(p->ch[i]) return false;
		}
		return true;
	}
	int getIndex(char c)const{
		return c - 'a';
	}
	TrieNode* newNode()const{
		TrieNode* p = new TrieNode;
		memset(p, 0, sizeof(TrieNode));
		return p;
	}
	void deleteTrie(TrieNode* p){
		if(!p) return;
		for(int i = 0; i < MAX; ++i) deleteTrie(p->ch[i]);
		delete p;
	}
public:
	WordTrie(){
		root = newNode();
	}
	~WordTrie(){
		deleteTrie(root);
	}
	void insertWord(const string& word){
		TrieNode* p = root;
		int i = 0, len = word.size(), k;
		for(; i < len; ++i){
			k = getIndex(word[i]);
			if(!p->ch[k]) p->ch[k] = newNode();
			p = p->ch[k];
			++p->freq;
		}
		p->eow = true;
	}
	bool findWord(const string& word)const{
		TrieNode* p = root;
		int i = 0, len = word.size(), k;
		for(; i < len; ++i){
			k = getIndex(word[i]);
			if(!p->ch[k]) return false;
			p = p->ch[k];
		}
		return p->eow;
	}
	string getPrefixRepresentation(const string& word) throw(WordNotFoundException){
		if(!findWord(word)) 
			throw WordNotFoundException(word);

		TrieNode* p = root;
		bool found = false;
		int i = 0, len = word.size(), k;
		for(; i < len && !found; ++i){
			k = getIndex(word[i]);
			if(p->ch[k]->freq < 2) found = true;
			p = p->ch[k];
		}
		return isLeaf(p) ? word.substr(0, i) : "";
	}
};


int main()
{
	WordTrie dict;
	string words[] = {"dog","done","good","go","gogo","gold","golf","why","which","while","zebra", "duck","dot"};
	int i, n = sizeof(words) / sizeof(words[0]);
	
	for(i = 0; i < n; ++i) dict.insertWord(words[i]);

	for(i = 0; i < n; ++i){
		try{
			string rep = dict.getPrefixRepresentation(words[i]);
			cout << words[i] << " -> " << rep << "\n";
		} catch(WordNotFoundException& e){
			cout << e.what() << "\n";
		}
	}

	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值