关闭

Trie树(字典树)_实现模糊查找(支持中文)

标签: Trie树字典树模糊匹配搜索词完整可运行代码
386人阅读 评论(0) 收藏 举报
分类:

搜索功能一般都有根据你的输入快速显示对应关键字的功能,比如你输入”刘”, 搜索框的下拉列表会显示“刘德华”,”刘若英”,”刘欢”等,你继续输入‘德’,将查询关键字变成”刘德”,显示的候选字列表会显示”刘德华”,”刘德华专辑”,”刘德华演唱会”等。下面将使用Trie树(字典树)来实现此功能。

一、什么是Trie树

Trie书又名字典树,字典是由一组词组成的集合,而字典树对这个集合进行了结构化的组织,将字典用另一种表达方式进行了表达。
首先字典书对一些具有公共前缀的词进行了“压缩”,大大减小了它占用的空间。同时对于字典内词的前缀检索也十分迅速,下面看一个图来理解下字典树:


上面的图就是字典树,字典树通过从根节点到子节点的路径来表达一个此,图中红色节点为一个词的最后一个节点,也就是说上面的树代表的单词有abc、ab、bd、dda,也就是红色节点的个数。其中,根节点不表示任何字符。字典树使用公共前缀压缩了存储结构,同时对于模糊匹配提供了很好的支持。

二、实现搜索词的模糊查找

(1)完整可运行的代码:

#include<iostream>
#include<string>
#include<map>
#include<vector>
using namespace std;
//字典树节点
class trieNode
{
public:
	trieNode() :count(0) {};
	//以当前节点结尾的字符串的个数
	int count;
	map<char16_t, trieNode*> child;
};
//字典树
class Trie
{
public:
	Trie() { root = new trieNode(); };
	void insert_string(const u16string& str);
	vector<u16string> get_str_pre(const u16string& str);
private:
	//辅助函数
	void add_str(trieNode* preNode, u16string str, vector<u16string>& ret);
	trieNode* search_str_pre(const u16string& str);

	trieNode* root;
};
//插入字符串,构建字典树
void Trie::insert_string(const u16string& str)
{
	if (!root || str.empty())
		return;

	trieNode* currentNode = root;

	for (auto& chr : str)
	{
		auto Iter = currentNode->child.find(chr);
		if (Iter == currentNode->child.end())
		{
			//如果当前字符不在字典树中,新建一个节点插入
			trieNode* newNode = new trieNode();
			currentNode->child.insert(make_pair(chr, newNode));
			currentNode = newNode;
		}
		else
		{
			//如果当前字符在字典书中,则将当前节点指向它的孩子
			currentNode = Iter->second;
		}
	}
	currentNode->count++;
}
//查找以str为前缀的节点
trieNode* Trie::search_str_pre(const u16string& str)
{
	if (!root || str.empty())
		return nullptr;

	trieNode* currentNode = root;
	for (auto& chr : str)
	{
		auto Iter = currentNode->child.find(chr);
		if (Iter != currentNode->child.end())
		{
			currentNode = Iter->second;
		}
		else
			return nullptr;
	}

	return currentNode;
}
//查找以str为前缀的所有字符串,保存在vector中返回
vector<u16string> Trie::get_str_pre(const u16string& str)
{
	vector<u16string> ret;
	trieNode* pre = search_str_pre(str);
	if (pre)
	{		
		add_str(pre, str, ret);
	}
	return ret;
}
//将preNode的所有子节点中字符串加入str前缀,然后插入到vector中
void Trie::add_str(trieNode* preNode, u16string str, vector<u16string>& ret)
{
	for (auto Iter = preNode->child.begin(); Iter != preNode->child.end(); ++Iter)
	{
		add_str(Iter->second, str + Iter->first, ret);
	}
	if (preNode->count != 0)
		ret.push_back(str);
}


int main()
{
	//为了终端能打印出中文
	setlocale(LC_ALL, "");
	//测试字符串用于构建字典树,utf-16编码,能同时保存中英文
	vector<u16string> hotworlds = { u"杨文婷",u"联系",u"杨洋洋",u"杨sir大警官",u"杨y文w婷t",u"杨文婷是小学生",
		u"杨钰莹",u"杨文婷ywt是小学生",u"联系a群众",u"阳光么",u"阳光明媚",u"ywt是小学生",u"联系ywt",u"杨文t爱吃面",u"杨文婷妹妹",
		u"杨光明眉",u"小学生",u"杨文婷爱吃面",u"我是小学生",u"我是中国人",u"ywt要吃面",u"y杨文婷",u"有问题" };
	Trie trie;
	for (auto& maString : hotworlds)
	{
		trie.insert_string(maString);
	}

	//输入“杨文婷”,返回所有以“杨文婷”为前缀的词
	vector<u16string> res = trie.get_str_pre(u"杨文婷");

	//打印结果
	for (auto& resString : res)
	{
		for (auto& chr : resString)
		{
			printf("%lc", chr);
		}
		printf("\n");
	}

	system("pause");
	return 0;
}
(二)运行结果:

1
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

数据结构——从英文字典树到中文字典树

昨天面试电话中的一道题,题目如下:给你一个姓名的集合,查找你的名字是否在里面出现,比如搜索姓氏为叶的人,那么会出现所有姓为叶的人,应该如何设计? 当时的回答是,姓为key,名为value,存放到mul...
  • a987073381
  • a987073381
  • 2016-08-09 23:08
  • 1887

中文trie树

这几天被汉字trie树小折腾了一下。 开始的时候想直接将单字节作为字典树的节点建树,虽然各个树的节点可能只是多字节字符的一部分,但是基本功能也能够支持。后来发现似乎有些问题,比如在做前向最大匹配分词的...
  • amblue
  • amblue
  • 2011-07-01 10:31
  • 4042

Java实现字典树TrieTree

为了准备阿里的网上笔试,这几天回顾了数据结构.看到字典树时,突然发现四六级的高频词可以用字典树找出来的.(应该不会是一个一个数出来的吧....) 构造字典树的过程如下: 1.首先确定树节点需要用怎么样...
  • lc0817
  • lc0817
  • 2015-08-19 13:04
  • 3402

字典树-大量字符串前缀及出现次数是否存在统计(Trie树-java)算法实现

前言        字典树又称单词查找树,它是一种树形结构,是一种哈希树的变种,典型应用是用于统计,保存大量的字符串(但不仅限于字符串),统计以是否有以某字符串最为前缀的字符串,有的话有多少,某字符串...
  • chenleixing
  • chenleixing
  • 2015-03-28 22:59
  • 8016

支持中文的基于词为基本粒度的前缀树(prefix trie)python实现

Trie树,也叫字典树、前缀树。可用于”predictive text”和”autocompletion”,亦可用于统计词频(边插入Trie树边更新或添加词频)。 在计算机科学中,trie,又称前缀...
  • yangxudong
  • yangxudong
  • 2014-10-28 13:35
  • 1968

hiho #1014 : Trie树 (字典树的建立和查找)

#1014 : Trie树 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,...
  • su20145104009
  • su20145104009
  • 2016-04-29 15:39
  • 4196

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表。前半部分跳跃表性质和操作的介绍直接摘自《让算法的效率跳起来--浅谈“跳跃表”的相关操作及其应用》上海市华东师范大学第二附属中学 魏冉。之后将附上...
  • zhongwen7710
  • zhongwen7710
  • 2014-09-14 22:10
  • 2433

字典树_Trie树_单词查找树

如果你觉得这篇博客对你有所帮助, 请在左边点个赞吧: ) 下面我们先提出几个问题: 已知有n个长度不等的母串, 以及一个长度为m的模式串, 求该模式串是否为其中一个母串的前缀. 这个问...
  • wjh2622075127
  • wjh2622075127
  • 2018-01-10 19:30
  • 9

Trie树(字典树)的C++实现

问题描述: Trie树 又称单词查找树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。 举个例子:os,...
  • hgqqtql
  • hgqqtql
  • 2015-01-01 01:10
  • 848

trie树(字典树)java实现

public class Trie{ private Node root; public Trie(){ root = new Node(' '); } ...
  • u012572955
  • u012572955
  • 2016-05-06 14:21
  • 639
    个人资料
    • 访问:10119次
    • 积分:441
    • 等级:
    • 排名:千里之外
    • 原创:32篇
    • 转载:3篇
    • 译文:0篇
    • 评论:6条
    最新评论