trie树,也称字典树,大家有没有想过你们在字典里查找一个单词是怎么样的。

首先,我们会查找第一个字符。

然后在第一个字符的范围内,查找第二个字符…以此类推

我们的字典树,就是这样的。

前置知识

字符串(都会?)

算法用途

快速搜索字符串

算法复杂度

时间

插入,删除,查询长度为 字典的长度python123 字典的长度怎么算_字典的长度python123 的字符串都是 字典的长度python123 字典的长度怎么算_算法_02

空间

n次插入,最大长度len,有x个不同字符:字典的长度python123 字典的长度怎么算_字典的长度python123_03

算法实现

插入

插入字符串 字典的长度python123 字典的长度怎么算_字典的长度python123_04

我们从根开始,往下走,根的深度为 字典的长度python123 字典的长度怎么算_字典树_05,当前深度为 字典的长度python123 字典的长度怎么算_字符串_06,我们看看当前节点有没有子节点 字典的长度python123 字典的长度怎么算_字典树_07字典的长度python123 字典的长度怎么算_字典的长度python123_04 的第 字典的长度python123 字典的长度怎么算_字符串_06 个字符的编号),有,继续往下走,没有,那就增加一个,然后继续走。直到执行完 字典的长度python123 字典的长度怎么算_算法_10

查询

查询字符串str。

同理,我们从根开始,往下走,根的深度为 字典的长度python123 字典的长度怎么算_字典树_05,当前深度为 字典的长度python123 字典的长度怎么算_字符串_06,我们看看当前节点有没有子节点 字典的长度python123 字典的长度怎么算_字典树_07字典的长度python123 字典的长度怎么算_字典的长度python123_04 的第 字典的长度python123 字典的长度怎么算_字符串_06个字符的编号),有,继续往下走,没有,就是没有这个字符串了

删除

删除字符串str。

同上,只是查找到后把只属于这个字符串的东西删了就行了。

算法优化

我们可以发现这算法时间复杂度很好,但是空间太大了。

所以我们考虑用一下奇怪的优化

正常的话要储存基本的字符串我们要每个节点 字典的长度python123 字典的长度怎么算_字符串_16

但是,我们可以考虑把一个字符拆分成 字典的长度python123 字典的长度怎么算_c++_17 个一次插入,这样一个字符串长度就为 字典的长度python123 字典的长度怎么算_字典的长度python123_18,然后每个节点儿子个数就为 字典的长度python123 字典的长度怎么算_算法_19

因为一般情况下都是 字典的长度python123 字典的长度怎么算_算法_20字典的长度python123 字典的长度怎么算_字符串_21

那原来空间为 字典的长度python123 字典的长度怎么算_算法_20,现在变为 字典的长度python123 字典的长度怎么算_字符串_23

减少了 字典的长度python123 字典的长度怎么算_字符串_24 倍!当然你也可以考虑拆成4份 字典的长度python123 字典的长度怎么算_字符串_25

代码

void add(string str)
{
	int p = 0;
	tree[p].cnt++;
	for(int i = 0; i < str.size(); i++)
	{
		int a = str[i] >> 4;
		if(tree[p].son[a])
		{
			p = tree[p].son[a];
		}
		else
		{
			if(sta.empty())
			{
				tree[p].son[a] = ++siz;
				p = siz;
			}
			else
			{
				tree[p].son[a] = sta.top();
				p = tree[p].son[a];
				sta.pop();
			}
		}
		tree[p].cnt++;
		a = str[i] & 0x0f;
		if(tree[p].son[a])
		{
			p = tree[p].son[a];
		}
		else
		{
			if(sta.empty()) 
			{
				tree[p].son[a] = ++siz;
				p = siz;
			}
			else
			{
				tree[p].son[a] = sta.top();
				p = tree[p].son[a];
				sta.pop();
			}
		}
		tree[p].cnt++;
	}
}
void del(string str)
{
	int p = 0;
	tree[p].cnt--;
	for(int i = 0; i < str.size(); i++)
	{
		int a = str[i] >> 4;
		if(tree[p].son[a])
		{
			int nowp = p;
			p = tree[p].son[a];
			tree[p].cnt--;
			if(!tree[p].cnt)
			{
					tree[nowp].son[a] = 0;
				sta.push(p);
			}
		}
		else
		{
			break;
		}
		a = str[i] & 0x0f;
		if(tree[p].son[a]) 
		{
			int nowp = p;
			p = tree[p].son[a];
			tree[p].cnt--;
			if(!tree[p].cnt)
			{
				tree[nowp].son[a] = 0;
				sta.push(p);
			}
		}
		else
		{
			break;
		}
	}
}

例题

字典的长度python123 字典的长度怎么算_字符串_26

字典的长度python123 字典的长度怎么算_c++_27