查找字典中某个公共前缀的所有单词

//Trie.h
/*
 * trie树统计公共前缀的单词集合、个数
 */

#include <set>
#include <string>
using namespace std;

#define BRANCH 26

struct Node
{
	Node * next[BRANCH];
	int prefix; // 此前缀的单词个数,为验证结果而加
	bool isStr;
	Node():prefix(0), isStr(false)
	{
		memset(next, 0, sizeof(next));
	}
};

class Trie
{
private:
	Node * root;
	set<string> * preSet;

    /* private:
	 * DFS() and freeNextArr() are private functions
	 *
	/* DFS find all the words from Node "ptr"
	 * 实际就是寻找“以当前前缀本身为单词”的单词
	 */
	void DFS(Node * ptr, string preStr)
	{
		for(int i = 0; i < BRANCH; ++i)
		{
			if(ptr->next[i] != NULL)
			{
				char chr[] = {'a' + i, '\0'};
				DFS(ptr->next[i],preStr+string(chr));
			}
			if(ptr->isStr)  // 存在当前前缀的单词
			{
				this->preSet->insert(preStr);
			}
		}
	}

	// free the next array
	void freeNextArr(Node * ptr)
	{
		for(int i = 0; i < BRANCH; ++i)
		{
			if(ptr->next[i] != NULL)
			{
				freeNextArr(ptr->next[i]);
			}
		}
		delete ptr;
	}

public:
	Trie()
	{
		root = new Node();
		preSet = new set<string> ();
	}

	// insert a word
	void insert(const char * word)
	{
		if(NULL == word)
		{
			return ;
		}
		Node * ptr = root;
		while(*word)
		{
			if(ptr->next[*word-'a'] == NULL)
			{
				ptr->next[*word-'a'] = new Node();
			}
			ptr->prefix ++;
			ptr = ptr->next[*word-'a'];
			++word;
		}
		ptr->isStr = true;
	}

	// find the location of the word
	Node * search(const char * word)
	{
		if(NULL == word)
		{
			return NULL;
		}
		Node * ptr = root;
		while(ptr && *word)
		{
			ptr = ptr->next[*word-'a'];
			++word;
		}
		return ptr;
	}

	// find the common prefix words set
	set<string> * findCommonPrefix_Set(const char * prefix)
	{
		if(NULL == prefix)
		{
			return NULL;
		}
		Node * ptr = search(prefix); // find location of prefix
		if(ptr == NULL)              // prefix not exist
		{
			return NULL;
		}
		DFS(ptr, string(prefix));   // DFS find commonPre words

		return this->preSet;
	}

	// clear the preSet
	void clearPreSet()
	{
		this->preSet->clear();
	}

	// free the memory
	void freeMemory()
	{
		this->freeNextArr(root);
		delete this->preSet;
	}
};



测试程序:

#include <iostream>
#include "Trie.h"

void main()
{
	Trie comPreTrie;
	comPreTrie.insert("abc");
	comPreTrie.insert("abcd");
	comPreTrie.insert("abcde");
	comPreTrie.insert("abcdef");
	comPreTrie.insert("abcdefg");
	comPreTrie.insert("cde");

	/* test the common prefix "abcd"
	 * 注,测试时默认输入合法字符,即 a-z
	 *    本文程序不对此做出检查
	 */
	Node * ptr = comPreTrie.search("abcd");
	if(ptr)
	{
		printf("num of words prefix by \"abcd\" is %d\n",
			ptr->isStr ? ptr->prefix + 1 : ptr->prefix);
	}else
	{
		printf("ptr for \"abcd\" is null\n");
	}

	set<string> * comPreSet
		= comPreTrie.findCommonPrefix_Set("abcd");
	if(comPreSet)
	{
		for(set<string>::iterator it = comPreSet->begin();
			it != comPreSet->end(); ++it)
		{
			printf("%s\n", (*it).c_str());
		}
	}else
	{
		printf("comPreSet for \"abcd\" is null\n");
	}
	comPreTrie.clearPreSet();

	printf("---------------\n");

	/* test the common prefix "word" */
	ptr = comPreTrie.search("word");
	if(ptr)
	{
		printf("num of words prefix by \"word\" is %d\n",
			ptr->isStr ? ptr->prefix + 1 : ptr->prefix);
	}else
	{
		printf("ptr for \"word\" is null\n");
	}

	comPreSet = comPreTrie.findCommonPrefix_Set("word");
	if(comPreSet)
	{
		for(set<string>::iterator it = comPreSet->begin();
			it != comPreSet->end(); ++it)
		{
			printf("%s\n", (*it).c_str());
		}
	}else
	{
		printf("comPreSet for \"word\" is null\n");
	}
	comPreTrie.clearPreSet();

	// free memory
	comPreTrie.freeMemory();
}
在C++,处理公共前缀串问题通常会使用Trie(也称为字典树或前缀树),这是一种用于高效存储和查找字符串的数据结构。当涉及到查找所有给定字符串的公共前缀时,可以按照以下步骤构建和操作Trie: 1. **构造Trie**: - 初始化一个空节点作为根。 - 对于每个输入的字符串,从第一个字符开始遍历。 - 每次遍历到一个新的字符,就在当前节点下创建一个新的子节点,并将指针移动到新节点。 - 当遇到字符串结束时,这个路径就是该字符串的完整前缀。 2. **查找公共前缀**: - 遍历输入的所有字符串,对每个字符串从根节点开始,如果下一个字符在当前路径上存在,则继续移动;如果不存在,则说明公共前缀已经结束。 - 当所有字符串都遍历完之后,最后一个到达的节点路径即为所有字符串的最长公共前缀。 ```cpp class TrieNode { public: char value; bool isEndOfWord; map<char, TrieNode*> children; TrieNode(char ch) : value(ch), isEndOfWord(false) {} }; TrieNode* buildTrie(vector<string>& words) { TrieNode* root = new TrieNode('$'); for (const auto& word : words) { TrieNode* node = root; for (char ch : word) { if (!node->children.count(ch)) { node->children[ch] = new TrieNode(ch); } node = node->children[ch]; } node->isEndOfWord = true; // 标记单词结束节点 } return root; } string longestCommonPrefix(vector<string>& strs) { TrieNode* root = buildTrie(strs); string prefix = ""; TrieNode* cur = root; for (const string& word : strs) { for (char ch : word) { if (cur->children.find(ch) == cur->children.end()) { break; } cur = cur->children[ch]; } if (prefix.empty()) { prefix = word.substr(0, cur->value != '$' ? cur->value - '$' : word.size()); } else { prefix = commonPrefix(prefix, word); } } return prefix; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值