Hihocode Trie树代码

今天AC了HiHocode 的第二道题,因为hihocode并不给测试提示,所以难度感觉leetcode高一些,比较恶心。

但是当出现AC的时候真是太高兴了,废话不多说,进入正题


我是华丽丽的分割线!

==============================================================


hihocode很善意的提供了提示,虽然分了三个,但是关键点还是两个

一是如何构建树

二是如何查询前置单词


Trie树是以边来保存字符的,博主一开始误以为是节点保存了,耗费了一点脑力。

另外,hihocode也提示了需要边插入边统计,于是我们的构造体就这样出现了。


需要注意的是hihocode 定义重复的单词算两个,博主一开始去掉了重复单词,于是WA了很久。

struct Node
{
	bool isWord;
	Node *child[Max];//save edge
	int L[Max];//save count

	Node()
	{
		isWord = false;

		for (int i = 0; i < Max; i++)
		{
			child[i] = NULL;			
		}

		for (int i = 0; i < Max; i++)
		{
			L[i] = 0;
		}
	}

	~Node()
	{
		for (int i = 0; i < Max; i++)
		{
			delete child[i];
		}
	}
};


插入单词:
void Insert(string word)
{
	Node *tempRoot = root;
	for (int i = 0; i < word.length(); i++)
	{
		tempRoot->L[word[i]-'a']++;
		if (tempRoot->child[word[i]-'a'] != NULL)
		{			
			tempRoot = tempRoot->child[word[i]-'a'];
		}
		else
		{
			Node *newNode = new Node();
			tempRoot->child[word[i]-'a'] = newNode;
			tempRoot = tempRoot->child[word[i]-'a'];
		}
		if (i == word.length() - 1)
		{
			if (tempRoot->isWord == false)
			{
				tempRoot->isWord = true;
			}			
		}
	}
}

因为是一边查找一边统计,所以其实可以不完全符合trie树也可以,是单词的那个节点不做标记也无法影响结果



查找单词/前缀 数量:

int find(string word)
{
	Node *tempRoot = root;
	for (int i = 0; i < word.length(); i++)
	{
		if (tempRoot->child[word[i]-'a'] == NULL)return 0;
		else
		{			
			if (i == word.length() - 1) return tempRoot->L[word[i]-'a'];
			tempRoot = tempRoot->child[word[i]-'a'];
		}
	}
}


接下来就贴上所有的代码

所有的代码中包含减去重复单词的函数,但是并没有用到:

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

const int Max = 26;
struct Node
{
	bool isWord;
	Node *child[Max];//save edge
	int L[Max];//save count

	Node()
	{
		isWord = false;

		for (int i = 0; i < Max; i++)
		{
			child[i] = NULL;			
		}

		for (int i = 0; i < Max; i++)
		{
			L[i] = 0;
		}
	}

	~Node()
	{
		for (int i = 0; i < Max; i++)
		{
			delete child[i];
		}
	}
};

Node * root = new Node();

void minusDuplicate(string word)
{
	Node *tempRoot = root;
	for (int i = 0; i < word.length(); i++)
	{
		tempRoot->L[word[i]-'a']--;
		tempRoot = tempRoot->child[word[i]-'a'];
	}
}

void Insert(string word)
{
	Node *tempRoot = root;
	for (int i = 0; i < word.length(); i++)
	{
		tempRoot->L[word[i]-'a']++;
		if (tempRoot->child[word[i]-'a'] != NULL)
		{			
			tempRoot = tempRoot->child[word[i]-'a'];
		}
		else
		{
			Node *newNode = new Node();
			tempRoot->child[word[i]-'a'] = newNode;
			tempRoot = tempRoot->child[word[i]-'a'];
		}
		if (i == word.length() - 1)
		{
			if (tempRoot->isWord == false)
			{
				tempRoot->isWord = true;
			}			
		}
	}
}

int find(string word)
{
	Node *tempRoot = root;
	for (int i = 0; i < word.length(); i++)
	{
		if (tempRoot->child[word[i]-'a'] == NULL)return 0;
		else
		{			
			if (i == word.length() - 1) return tempRoot->L[word[i]-'a'];
			tempRoot = tempRoot->child[word[i]-'a'];
		}
	}
}



int main()
{
	int count = 0;
	cin >> count;
	string insertStr;
	for (int i = count; i > 0; i--)
	{
		cin >> insertStr;
		Insert(insertStr);
	}
	cin >> count;
	for (int i = count; i > 0; i--)
	{
		cin >> insertStr;
		cout<<find(insertStr)<<endl;
	}
	return 0;
}




### 回答1: 这是一段基于 Python 的 trie 代码: ``` class TrieNode: def __init__(self): self.children = {} self.is_word = False class Trie: def __init__(self): self.root = TrieNode() def insert(self, word): node = self.root for char in word: if char not in node.children: node.children[char] = TrieNode() node = node.children[char] node.is_word = True def search(self, word): node = self.root for char in word: if char not in node.children: return False node = node.children[char] return node.is_word def starts_with(self, prefix): node = self.root for char in prefix: if char not in node.children: return False node = node.children[char] return True ``` 这个 trie 的实现包含了三个操作:插入单词,搜索单词以及搜索前缀。 ### 回答2: Trie,也称为字典或前缀,是一种特殊的数据结构,通常用于快速检索和存储字符串集合。下面是一个用Python编写的Trie的基本代码: ```python class TrieNode: def __init__(self): self.children = {} self.is_end_of_word = False class Trie: def __init__(self): self.root = TrieNode() def insert(self, word): current_node = self.root for char in word: if char not in current_node.children: current_node.children[char] = TrieNode() current_node = current_node.children[char] current_node.is_end_of_word = True def search(self, word): current_node = self.root for char in word: if char not in current_node.children: return False current_node = current_node.children[char] return current_node.is_end_of_word def starts_with(self, prefix): current_node = self.root for char in prefix: if char not in current_node.children: return False current_node = current_node.children[char] return True ``` 上述代码中,`TrieNode`类表示Trie的节点。每个节点包含一个子节点字典和一个布尔值`is_end_of_word`,用于标记是否是一个单词的结尾。 `Trie`类包含了Trie的基本操作。其中`insert`方法用于向Trie中插入一个单词,`search`方法用于查找一个单词是否存在,`starts_with`方法用于检查一个前缀是否存在。 这段代码实现了一个简单的Trie,可以用于处理一些与字符串相关的问题,如单词的插入、查找和前缀匹配等操作。需要注意的是,上述代码只是Trie的基本实现,仍有许多优化和扩展的空间,如节点压缩、前缀搜索等。 ### 回答3: Trie,也被称为字典或前缀,是一种常用的数据结构,用于存储和搜索字符串集合。下面是一个简单的Trie代码示例: ```python class TrieNode: def __init__(self): self.children = {} # 子节点集合 self.is_word = False # 标记是否为一个完整的单词 class Trie: def __init__(self): self.root = TrieNode() # 初始化根节点 def insert(self, word): node = self.root # 从根节点开始 for char in word: if char not in node.children: node.children[char] = TrieNode() # 如果字符不在子节点集合中,则添加一个新节点 node = node.children[char] # 继续处理下一个字符 node.is_word = True # 标记最后一个节点为一个完整的单词 def search(self, word): node = self.root for char in word: if char not in node.children: return False # 如果字符在任何节点中都不存在,则单词不存在 node = node.children[char] return node.is_word # 判断最后一个节点是否为一个完整的单词 def startsWith(self, prefix): node = self.root for char in prefix: if char not in node.children: return False # 如果字符在任何节点中都不存在,则前缀不存在 node = node.children[char] return True # 返回True,表示存在以该前缀开头的单词 ``` 这段代码定义了两个类:`TrieNode`表示一个Trie的节点,包含子节点集合和标记是否为一个完整的单词;`Trie`表示Trie,其中的方法包括`insert`插入一个单词,`search`搜索是否存在一个单词,以及`startsWith`判断是否存在以某个前缀开头的单词。 这个Trie代码示例可以用于构建和查询字符串集合。通过不断向Trie插入单词,可以将它们按字符顺序分解成状结构,通过遍历节点来搜索和判断单词是否存在。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值