精华内容
下载资源
问答
  • Python实现Trie树

    2018-06-13 11:00:23
    用Python实现Trie树的应用,并可以对英汉词典进行导入和检索、添加和删除,最终可以将导入的英汉词典保存到本地磁盘。内附两个.py文件,分别是tree.py和d_gui.py,tree.py是类和方法,d_gui.py是图形界面;一个.txt...
  • Trie树也称字典树,因为其效率很高,所以在在字符串查找、前缀匹配等中应用很广泛,其高效率是以空间为代价的。 一.Trie树的原理  利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低...

     Trie树也称字典树,因为其效率很高,所以在在字符串查找、前缀匹配等中应用很广泛,其高效率是以空间为代价的。

    一.Trie树的原理

        利用串构建一个字典树,这个字典树保存了串的公共前缀信息,因此可以降低查询操作的复杂度。

        下面以英文单词构建的字典树为例,这棵Trie树中每个结点包括26个孩子结点,因为总共有26个英文字母(假设单词都是小写字母组成)。

        则可声明包含Trie树的结点信息的结构体:

    复制代码
    #define MAX 26

    typedef struct TrieNode //Trie结点声明
    {
    bool isStr; //标记该结点处是否构成单词
    struct TrieNode *next[MAX]; //儿子分支
    }Trie;
    复制代码

        其中next是一个指针数组,存放着指向各个孩子结点的指针。

        如给出字符串"abc","ab","bd","dda",根据该字符串序列构建一棵Trie树。则构建的树如下:

        

     Trie树的根结点不包含任何信息,第一个字符串为"abc",第一个字母为'a',因此根结点中数组next下标为'a'-97的值不为NULL,其他同理,构建的Trie树如图所示,红色结点表示在该处可以构成一个单词。很显然,如果要查找单词"abc"是否存在,查找长度则为O(len),len为要查找的字符串的长度。而若采用一般的逐个匹配查找,则查找长度为O(len*n),n为字符串的个数。显然基于Trie树的查找效率要高很多。

    但是却是以空间为代价的,比如图中每个结点所占的空间都为(26*4+1)Byte=105Byte,那么这棵Trie树所占的空间则为105*8Byte=840Byte,而普通的逐个查找所占空间只需(3+2+2+3)Byte=10Byte。

    二.Trie树的操作

        在Trie树中主要有3个操作,插入、查找和删除。一般情况下Trie树中很少存在删除单独某个结点的情况,因此只考虑删除整棵树。

    1.插入

      假设存在字符串str,Trie树的根结点为root。i=0,p=root。

      1)取str[i],判断p->next[str[i]-97]是否为空,若为空,则建立结点temp,并将p->next[str[i]-97]指向temp,然后p指向temp;

       若不为空,则p=p->next[str[i]-97];

      2)i++,继续取str[i],循环1)中的操作,直到遇到结束符'\0',此时将当前结点p中的isStr置为true。

    2.查找

      假设要查找的字符串为str,Trie树的根结点为root,i=0,p=root

      1)取str[i],判断判断p->next[str[i]-97]是否为空,若为空,则返回false;若不为空,则p=p->next[str[i]-97],继续取字符。

      2)重复1)中的操作直到遇到结束符'\0',若当前结点p不为空并且isStr为true,则返回true,否则返回false。

    3.删除

      删除可以以递归的形式进行删除。

    测试程序:

    /*Trie树(字典树) 2011.10.10*/ 
    
    #include <iostream>
    #include<cstdlib>
    #define MAX 26
    using namespace std;
    
    typedef struct TrieNode    					//Trie结点声明 
    {
    	bool isStr;          				   //标记该结点处是否构成单词 
    	struct TrieNode *next[MAX];            //儿子分支 
    }Trie;
    
    void insert(Trie *root,const char *s)     //将单词s插入到字典树中 
    {
    	if(root==NULL||*s=='\0')
    		return;
    	int i;
        Trie *p=root;
    	while(*s!='\0')
    	{
    		if(p->next[*s-'a']==NULL)        //如果不存在,则建立结点 
    		{
    			Trie *temp=(Trie *)malloc(sizeof(Trie));
    			for(i=0;i<MAX;i++)
    			{
    				temp->next[i]=NULL;
    			}
    			temp->isStr=false;
    			p->next[*s-'a']=temp;
    			p=p->next[*s-'a'];	
    		}	
    		else
    		{
    			p=p->next[*s-'a'];
    		}
    		s++;
    	}
    	p->isStr=true;	                    //单词结束的地方标记此处可以构成一个单词 
    }
    
    int search(Trie *root,const char *s)  //查找某个单词是否已经存在 
    {
    	Trie *p=root;
    	while(p!=NULL&&*s!='\0')
    	{
    		p=p->next[*s-'a'];
    		s++;
    	}
    	return (p!=NULL&&p->isStr==true);      //在单词结束处的标记为true时,单词才存在 
    }
    
    void del(Trie *root)                      //释放整个字典树占的堆区空间 
    {
    	int i;
    	for(i=0;i<MAX;i++)
    	{
    		if(root->next[i]!=NULL)
    		{
    			del(root->next[i]);
    		}
    	}
    	free(root);
    }
    
    int main(int argc, char *argv[])
    {
    	int i;
    	int n,m;                              //n为建立Trie树输入的单词数,m为要查找的单词数 
    	char s[100];
    	Trie *root= (Trie *)malloc(sizeof(Trie));
    	for(i=0;i<MAX;i++)
    	{
    		root->next[i]=NULL;
    	}
    	root->isStr=false;
        scanf("%d",&n);
        getchar();
    	for(i=0;i<n;i++)                 //先建立字典树 
    	{
    		scanf("%s",s);
    		insert(root,s);
    	}
    	while(scanf("%d",&m)!=EOF)
    	{
    		for(i=0;i<m;i++)                 //查找 
    		{
    			scanf("%s",s);
    			if(search(root,s)==1)
    				printf("YES\n");
    			else
    				printf("NO\n");
    		}
    		printf("\n"); 	
    	}
    	del(root);                         //释放空间很重要 
    	return 0;
    }
    

    训练题目:

    http://acm.hdu.edu.cn/showproblem.php?pid=1671

    http://acm.hdu.edu.cn/showproblem.php?pid=1075

    http://acm.hdu.edu.cn/showproblem.php?pid=1251

    展开全文
  • if (trie[r][t ^ 1] && cnt[trie[r][t ^ 1]]) /// 有子节点且子节点有经过的字符串 r = trie[r][t ^ 1]; else r = trie[r][t]; } return a ^ val[r]; } int main() { int T; scanf("%d", &T); while...

    Chip Factory

    Time Limit: 18000/9000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
    Total Submission(s): 5067    Accepted Submission(s): 2280


     

    Problem Description

    John is a manager of a CPU chip factory, the factory produces lots of chips everyday. To manage large amounts of products, every processor has a serial number. More specifically, the factory produces n chips today, the i-th chip produced this day has a serial number si.

    At the end of the day, he packages all the chips produced this day, and send it to wholesalers. More specially, he writes a checksum number on the package, this checksum is defined as below:

    maxi,j,k(si+sj)⊕sk


    which i,j,k are three different integers between 1 and n. And ⊕ is symbol of bitwise XOR.

    Can you help John calculate the checksum number of today?

     

     

    Input

    The first line of input contains an integer T indicating the total number of test cases.

    The first line of each test case is an integer n, indicating the number of chips produced today. The next line has n integers s1,s2,..,sn, separated with single space, indicating serial number of each chip.

    1≤T≤1000
    3≤n≤1000
    0≤si≤109
    There are at most 10 testcases with n>100

     

     

    Output

    For each test case, please output an integer indicating the checksum number in a line.

     

     

    Sample Input

     

    2

    3

    1 2 3

    3

    100 200 300

     

     

    Sample Output

     

    6

    400

     

     

    Source

    2015ACM/ICPC亚洲区长春站-重现赛(感谢东北师大)

     

     

    #include <bits/stdc++.h>
    using namespace std;
    
    const int mt = 1005, mn = 1010, ms = 1e9 + 10;
    
    int s[mn];
    
    int num;
    int trie[mn * 35][2], val[mn * 35], cnt[mn * 35];
    void add(int a)
    {
    	int r = 0;
    	for (int i = 31; i >= 0; i--)
    	{
    		int t = ((1 << i) & a) ? 1 : 0;  /// 01字典树子节点
    		if (!trie[r][t])
    			trie[r][t] = ++num;
    		r = trie[r][t];
    		cnt[r]++; /// 经过r的次数
    	}
    	val[r] = a;
    }
    void des(int a) /// 删除字符串
    {
    	int r = 0;
    	for (int i = 31; i >= 0; i--)
    	{
    		int t = ((1 << i) & a) ? 1 : 0;
    		r = trie[r][t];
    		cnt[r]--; /// 经过r次数 -1
    	}
    }
    int ask(int a)
    {
    	int r = 0;
    	for (int i = 31; i >= 0; i--)
    	{
    		int t = ((1 << i) & a) ? 1 : 0;
    		if (trie[r][t ^ 1] && cnt[trie[r][t ^ 1]]) /// 有子节点且子节点有经过的字符串
    			r = trie[r][t ^ 1];
    		else
    			r = trie[r][t];
    	}
    	return a ^ val[r];
    }
    
    int main()
    {
    	int T;
    	scanf("%d", &T);
    	while (T--)
    	{
    		num = 0;
    		memset(cnt, 0, sizeof cnt);
    		memset(val, 0, sizeof val);
    		memset(trie, 0, sizeof trie);
    
    		int n;
    		scanf("%d", &n);
    		for (int i = 1; i <= n; i++)
    		{
    			scanf("%d", &s[i]);
    			add(s[i]);
    		}
    		int ans = 0;
    		for (int i = 1; i <= n; i++) // 枚举
    		{
    			des(s[i]); /// 删除枚举到的字符串
    			for (int j = i + 1; j <= n; j++)
    			{
    				des(s[j]);
    				ans = max(ans, ask(s[i] + s[j])); /// 计算当前最大异或值
    				add(s[j]); /// 将删除的字符串重新加入
    			}
    			add(s[i]);
    		}
    		printf("%d\n", ans);
    	}
    	return 0;
    }
    

     

    展开全文
  • Trie 字典 删除操作

    千次阅读 2014-05-30 20:48:18
    字典删除操作: 1 没找到直接返回 2 找到叶子节点的时候,叶子节点的count标志清零,代表不是叶子节点了 3 如果当前节点没有其他孩子节点的时候,可以删除这个节点 判断是否需是叶子节点,就检查叶子节点的...

    字典树的删除操作:

    1 没找到直接返回

    2 找到叶子节点的时候,叶子节点的count标志清零,代表不是叶子节点了

    3 如果当前节点没有其他孩子节点的时候,可以删除这个节点

    判断是否需是叶子节点,就检查叶子节点的count标志就可以了。

    判断是否有其他孩子节点就需要循环26个节点了,如果都为空,那么就没有其他孩子节点了。


    #include <stdio.h>
    #include <stdlib.h>
    #include <iostream>
    #include <vector>
    #include <string>
    
    class TrieDelete_2
    {
    	static const int ARRAY_SIZE = 26;
    	struct Node
    	{
    		int val;
    		Node *children[ARRAY_SIZE];
    		explicit Node(int k = 0) : val(k)
    		{
    			for (int i = 0; i < ARRAY_SIZE; i++)
    			{
    				children[i] = NULL;
    			}
    		}
    		~Node()
    		{
    			for (int i = 0; i < ARRAY_SIZE; i++)
    			{
    				if (children[i]) delete children[i];
    				children[i] = NULL;
    			}
    		}
    	};
    
    	struct Trie
    	{
    		Node *emRoot;
    		int count;
    		explicit Trie(int c = 0) : count(c)
    		{
    			emRoot = new Node;//emRoot(NULL) {},应该分配emRot空间比较合理
    		}
    		~Trie()
    		{
    			if (emRoot) delete emRoot;
    			emRoot = NULL;
    		}
    	};
    
    	void insert(Trie *trie, char keys[])
    	{
    		int len = strlen(keys);
    
    		Node *pCrawl = trie->emRoot;
    		trie->count++;
    
    		for (int i = 0; i < len; i++)
    		{
    			int k = keys[i] - 'a';
    			if (!pCrawl->children[k])
    			{
    				pCrawl->children[k] = new Node;
    			}
    			pCrawl = pCrawl->children[k];
    		}
    		pCrawl->val = trie->count;
    	}
    
    	bool search(Trie *trie, char key[])
    	{
    		int len = strlen(key);
    		Node *pCrawl = trie->emRoot;
    		for (int i = 0; i < len; i++)
    		{
    			int k = key[i] - 'a';
    			if (!pCrawl->children[k])
    			{
    				return false;
    			}
    			pCrawl = pCrawl->children[k];
    		}
    		return pCrawl->val != 0;
    	}
    
    	bool isFreeNode(Node *n)
    	{
    		for (int i = 0; i < ARRAY_SIZE; i++)
    		{
    			if (n->children[i]) return false;
    		}
    		return true;
    	}
    
    	bool isLeaf(Node *n)
    	{
    		return n->val != 0;
    	}
    
    	bool deleteHelp(Node *n, char key[], int lv, int len)
    	{
    		if (n)
    		{
    			if (lv == len)
    			{
    				if (isLeaf(n))
    				{
    					n->val = 0;
    					if (isFreeNode(n))
    					{
    						delete n, n = NULL;
    						return true;
    					}
    					return false;
    				}
    			}
    			else
    			{
    				int k = key[lv] - 'a';
    				if(deleteHelp(n->children[k], key, lv+1, len))
    				{
    					if (!isLeaf(n) && isFreeNode(n))
    					{
    						delete n, n = NULL;
    						return true;
    					}
    					return false;
    				}
    			}
    		}
    		return false;
    	}
    
    	void deleteKey(Trie *trie, char key[])
    	{
    		int len = strlen(key);
    		if (len > 0)
    		{
    			deleteHelp(trie->emRoot, key, 0, len);
    		}
    	}
    
    public:
    	TrieDelete_2()
    	{
    		char keys[][8] = {"she", "sells", "sea", "shore", "the", "by", "sheer"};
    		Trie *trie = new Trie; 
    
    		for(int i = 0; i < ARRAY_SIZE(keys); i++)
    		{
    			insert(trie, keys[i]);
    		}
    
    		deleteKey(trie, keys[0]);
    
    		printf("%s %s\n", "she", search(trie, "she") ? "Present in trie" : "Not present in trie");
    
    		delete trie;
    	}
    };


    展开全文
  • Trie树详解(转)

    2021-01-30 11:26:38
    以下为我研究时参考过的链接(有很多,这里我只列出我记得的):1、字典的概念字典,因为它的搜索快捷的特性被单词搜索系统使用,故又称单词查找。它是一种形结构的数据结构。之所以快速,是因为它用空间代替...

    特别声明

    本文只是一篇笔记类的文章,所以不存在什么抄袭之类的。

    以下为我研究时参考过的链接(有很多,这里我只列出我记得的):

    1、字典树的概念

    字典树,因为它的搜索快捷的特性被单词搜索系统使用,故又称单词查找树。它是一种树形结构的数据结构。之所以快速,是因为它用空间代替了速度。

    2、字典树的特点:

    字典树有三个基本性质:

    1、根节点不包含字符,除根节点外每一个节点都只包含一个字符

    2、从根节点到某一个节点,路径上经过的字符连接起来,就是该节点对应的字符串

    3、每个节点的所有子节点包含的字符都不相同。

    3、一个包含以下字符串的字典树结构如下图所示:

    addadbc

    bye

    5849b93f58e319bf56e706ff2d08226b.png

    Trie树.png

    4、字典树的应用场景

    1)、字符串的快速查找

    给出N个单词组成的熟词表,以及一篇全用小写英文书写的文章,请你按最早出现的顺序写出所有不在熟词表中的生词。

    在这道题中,我们可以用数组枚举,用哈希,用字典树,先把熟词建一棵树,然后读入文章进行比较,这种方法效率是比较高的。

    2)、字典树在“串”排序方面的应用

    给定N个互不相同的仅由一个单词构成的英文名,让你将他们按字典序从小到大输出

    用字典树进行排序,采用数组的方式创建字典树,这棵树的每个节点的所有儿子

    很显然地按照其字母大小排序,对这棵树进行先序遍历即可。

    3)、字典树在最长公共前缀问题的应用

    对所有串建立字典树,对于两个串的最长公共前缀的长度即他们所在的节点的公共祖先个数,于是,问题就转化为最近公共祖先问题。

    5、字典树的数据结构

    由以上描述我们可以知道,字典树的数据结构如下:

    class TrieNode {

    char c;

    int occurances;

    Map children;

    }

    对以上属性的描述:

    1、c, 保存的是该节点的数据,只能是一个字符(注意是一个)

    2、occurances, 从单词意思应该知道是发生频率的意思。occurances 是指 当前节点所对应的字符串在字典树里面出现的次数。

    3、children, 就是当前节点的子节点,保存的是它的下一个节点的字符。

    7、根据字符串常用的功能,字典树类要实现的特性

    1)查询是否包含某个字符串

    2)查询某个字符串出现的频率

    3)插入某个字符串

    4)删除某个字符串

    5)获取整个字典树的规模,即字典树中包含的不同字符串的个数

    基于以上考虑,可以建立一个接口,Trie类只需要实现这个接口即可

    8、基于6所描述的特性创建抽象类如下:

    public abstract class AbTrie {

    // 判断字典树中是否有该字符串。

    public abstract boolean contains(String word);

    // 返回该字符串在字典树中出现的次数。

    public abstract int frequency(String word);

    // 插入一个字符串。

    public abstract int insert(String word);

    // 删除一个字符串。

    public abstract boolean remove(String word);

    // 整个字典树中不同字符串的个数,也就是保存的不同字符串的个数。

    public abstract int size();

    }

    各个抽象方法的描述已经很详细的解释了,这里不再赘述

    9、下面讲解接口中各个方法的实现原理

    1)插入字符串

    1、从头到尾遍历字符串的每一个字符

    2、从根节点开始插入,若该字符存在,那就不用插入新节点,要是不存在,则插入新节点

    3、然后顺着插入的节点一直按照上述方法插入剩余的节点

    4、为了统计每一个字符串出现的次数,应该在最后一个节点插入后occurances++,表示这个字符串出现的次数增加一次

    2)删除一个字符串

    1、从root结点的孩子开始(因为每一个字符串的第一个字符肯定在root节点的孩子里),判断该当前节点是否为空,若为空且没有到达所要删除字符串的最后一个字符,则不存在该字符串。若已经到达叶子结点但是并没有遍历完整个字符串,说明整个字符串也不存在,例如要删除的是'harlan1994',而有'harlan'.

    2、只有当要删除的字符串找到时并且最后一个字符正好是叶子节点时才需要删除,而且任何删除动作,只能发生在叶子节点。例如要删除'byebye',但是字典里还有'byebyeha',说明byebye不需要删除,只需要更改occurances=0即可标志字典里已经不存在'byebye'这个字符串了

    3、当遍历到最后一个字符时,也就是说字典里存在该字符,必须将当前节点的occurances设为0,这样标志着当前节点代表的这个字符串已经不存在了,而要不要删除,需要考虑2中所提到的情况,也就是说,只有删除只发生在叶子节点上。

    3)获取字符串出现的次数

    1、我们在设计数据结构的时候就有了一个occurances属性

    2、只需要判断该字符串是否存在,若存在则返回对应字符下的occurances即可

    4)是否存在某个字符串

    1、查询字符串是从第一个字符开始的

    2、当查询的位置已经超过了字符串的长度,比如要查的是“adc”,但是我们查到树的深度已经超过了c,那么肯定是不存在的

    3、如果查询的位置刚好为字符串的长度,这时,就可以判断当前节点的符合要求孩子是否存在,若存在,则字符串存在,否则不存在

    4、其余情况则需要继续深入查询,若符合要求的孩子节点存在,则继续查询,否则不存在。

    5)整棵Trie树的大小,即不同字符串的个数

    1、返回Trie数据结构中的size属性即可。

    2、size属性会在insert,remove两个操作后进行更新

    10、代码实现

    1)插入字符串

    int insert(String s, int pos) {

    //如果插入空串,则直接返回

    //此方法调用时从pos=0开始的递归调用,pos指的是插入的第pos个字符

    if (s == null || pos >= s.length())

    return 0;

    // 如果当前节点没有孩子节点,则new一个

    if (children == null)

    children = new HashMap();

    //创建一个TrieNode

    char c = s.charAt(pos);

    TrieNode n = children.get(c);

    //确保字符保存在即将要插入的节点中

    if (n == null) {

    n = new TrieNode(c);

    children.put(c, n);

    }

    //插入的结束时直到最后一个字符插入,返回的结果是该字符串出现的次数

    //否则继续插入下一个字符

    if (pos == s.length() - 1) {

    n.occurances++;

    return n.occurances;

    } else {

    return n.insert(s, pos + 1);

    }

    }

    2)删除字符串

    boolean remove(String s, int pos) {

    if (children == null || s == null)

    return false;

    //取出第pos个字符,若不存在,则返回false

    char c = s.charAt(pos);

    TrieNode n = children.get(c);

    if (n == null)

    return false;

    //递归出口是已经到了字符串的最后一个字符,秀嘎occurances=0,代表已经删除了

    //否则继续递归到最后一个字符

    boolean ret;

    if (pos == s.length() - 1) {

    int before = n.occurances;

    n.occurances = 0;

    ret = before > 0;

    } else {

    ret = n.remove(s, pos + 1);

    }

    // 1. If we want to remove 'hello', but there is a 'helloa', you do not

    // need to remove the saved chars, because its occurances has been

    // settled

    // 0 witch means the string s no longer exists.

    // 2.its occurances must be 0, for exmaple,

    // when you want to remove 'harlan1994', but there is no such sequence,

    // there is only 'harlan'

    // so when we reach the last char 'n',the pos != s.length() - 1, its

    // occurances can't be

    // settled into 0, and it > 0, so it is not the sequence that need to be

    // removed.

    // if we just removed a leaf, prune upwards.

    //删除之后,必须删除不必要的字符

    //比如保存的“Harlan”被删除了,那么如果n保存在叶子节点,意味着它虽然被标记着不存在了,但是还占着空间

    //所以必须删除,但是如果“Harlan”删除了,但是Trie里面还保存这“Harlan1994”,那么久不需要删除字符了

    if (n.children == null && n.occurances == 0) {

    children.remove(n.c);

    if (children.size() == 0)

    children = null;

    }

    return ret;

    }

    3)求一个字符串出现的次数

    TrieNode lookup(String s, int pos) {

    if (s == null)

    return null;

    //如果找的次数已经超过了字符的长度,说明,已经递归到超过字符串的深度了,表明字符串不存在

    if (pos >= s.length() || children == null)

    return null;

    //如果刚好到了字符串最后一个,则只需要返回最后一个字符对应的结点,若节点为空,则表明不存在该字符串

    else if (pos == s.length() - 1)

    return children.get(s.charAt(pos));

    //否则继续递归查询下去,直到没有孩子节点了

    else {

    TrieNode n = children.get(s.charAt(pos));

    return n == null ? null : n.lookup(s, pos + 1);

    }

    }

    以上kookup方法返回值是一个TrieNode,要找某个字符串出现的次数,只需要看其中的n.occurances即可。

    要看是否包含某个字符串,只需要看是否为空节点即可。

    11、下面来一个应用,题目如下:

    不考虑字母大小写,在一篇文章中只有英文,不包含其余任何字符,求这篇文章中不同单词的个数。

    并求所给单词的出现次数。

    1)建立一个测试类Sample,添加两个方法分别求以上两个问题

    2)添加一个求取文件内容,并添加字符串到字典树中的方法,关键代码如下:

    ...

    private void init() {

    try {

    InputStream in = new FileInputStream(new File(

    "E:\\Eclipse\\trie\\src\\com\\harlan\\trie\\bible.txt"));

    addToDictionary(in);

    } catch (Exception e) {

    e.printStackTrace();

    }

    }

    public void addToDictionary(InputStream f) throws IOException,

    FileNotFoundException {

    long t = System.currentTimeMillis();

    final int bufSize = 1000;

    int read;

    int numWords = 0;

    InputStreamReader fr = null;

    try {

    fr = new InputStreamReader(f);

    char[] buf = new char[bufSize];

    while ((read = fr.read(buf)) != -1) {

    // TODO modify this split regex to actually be useful

    String[] words = new String(buf, 0, read).split("\\W");

    for (String s : words) {

    mTrie.insert(s);

    numWords++;

    }

    }

    } finally {

    if (fr != null) {

    try {

    fr.close();

    } catch (IOException e) {

    }

    }

    }

    System.out.println("Read from file and inserted " + numWords

    + " words into trie in " + (System.currentTimeMillis() - t)

    / 1000.0 + " seconds.");

    }

    public int getSize() {

    if (mTrie != null) {

    return mTrie.size();

    }

    return 0;

    }

    public int getCount(String s) {

    return mTrie.frequency(s);

    }

    测试结果截图如下:

    55118e05a7727d9cb8c8803d009b32d5.png

    测试.png

    展开全文
  • 单词查找树简介代码实现单词查找树简介Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用...
  • Trie树,也称作是字典树,是一种哈希树的变种,查询效率较高。Trie树可以用于统计或者排序大量的字符串,比如对一系列字符串按照字典序排序。字典树是一个多叉树,每一个节点上存储的不是一个字符串,而是一个字符,...
  • trie树的基本操作

    2021-04-15 20:12:48
    trie树 介绍 Trie????(发音类似 “try”)或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。 ​ 在计算机科学中,trie,又...
  • 字符串匹配算法(Trie树

    千次阅读 多人点赞 2019-06-25 01:25:37
    Trie树概念2. Trie树操作2.1 存储2.2 插入2.3 查询 1. Trie树概念 Trie树,也叫字典树,它是一个树形结构。是一种专门处理字符串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串。 Trie树本质,...
  • Trie树(字典树)

    2020-03-06 20:43:02
    Trie树一般指字典树,又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用...
  • 小白详解 Trie

    2021-07-18 14:25:41
    一、引言 最近学习自然语言处理(NLP)相关的知识,认识了 Trie 这种形数据结构,在 NLP 中一般会用其存储大量的字典字符以用于文本的快速分词;除此之外,典型应用场景还包括大批量文本的:词频统计、字符串查询...
  • 一棵用List来存储子结点的字典——当然,也可以用哈希表等形式存储。 一、构建思路 Step1 设计结点——数据结构 Step2 实现相应的操作方法——增删改查 Step1 设计结点 我们需要该结点能够存储以下数据: 该...
  • trie树字典树的插入和删除

    千次阅读 2016-10-11 14:18:58
    #include #include using namespace std;...typedef struct Trie_node { int count; // 统计单词前缀出现的次数 struct Trie_node* next[26]; // 指向各个子树的指针 bool exist; // 标记该结点处是否构
  • 双数组trie树介绍

    2021-02-28 19:16:52
    但是Trie最大的缺点就是占用空间过大,很容易爆内存,当然在ACM里对Trie树也有相应的优化,如限定高度,对分支较少的节点使用非随机访问的结构(减少宽度),但这些都是牺牲部分查找效率换取的。这里介绍一...
  • Trie树 c++实现

    千次阅读 2015-08-15 17:29:12
    Trie,又称单词查找、前缀,是一种多叉结构。 与二叉查找不同,键不是直接保存在节点中,而是由节点在中的位置决定。一个节点的所有子孙都有相同的前缀,也就是这个节点对应的字符串,而根节点对应空字符...
  • (3)删除;(4)前缀统计;(5)搜索 实现一:通过字典的嵌套来实现 class Trie(object): """ 实现1:通过python自带的字典结构 具有如下基本功能: (1)根据一组words进行TrieTree的构建 (2)添加某个...
  • Trie树概述   Trie树,又称字典树、前缀树、单词查找树、键树,是一种多叉树形结构,是一种哈希树的变种。Trie这个术语来自于retrieval,发音为/tri:/ “tree”,也有人读为/traɪ/ “try”。Trie树典型应用是用于...
  • Trie树(压缩Trie树及Double-Array Trie)

    千次阅读 2015-09-07 18:30:03
    英文字母的Trie树为26叉树,数字的Trie树为10叉树;All the descendants of a node have a common prefix of the sequence associated with that node, and the root is associated with the empty sequen
  • 前言 目前做分词比较流行的是用深度学习来做,比如用循环神经网络和条件随机场,也有直接用条件随机场或隐马尔科夫模型的。前面也实现过上面几种,效果挺不错,基于隐马尔科夫模型...Trie树结构 Trie 是一种搜索树...
  • Trie树

    千次阅读 2015-03-12 21:16:22
    定义:又称字典树或单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串...
  • 什么是 Trie

    2020-12-27 17:37:51
    Trie 是一种多叉的结构,每个节点保存一个字符,一条路径表示一个字符串。 下图表示了字符串: him 、 her 、 cat 、 no 、 nova 构成的 Trie 。 从图中可以看出 Trie 包含以下性质: 根节点不包含字符,...
  • 度熊手上有一本神奇的字典,你可以在它里面做如下三个操作:1、insert : 往神奇字典中插入一个单词2、delete: 在神奇字典中删除所有前缀等于给定字符串的单词3、search: 查询是否在神奇字典中有一个字符串的前缀等于...
  • 字典树(Trie树)详解

    2017-05-14 12:29:05
    字典树(Trie树)  字典树,又称单词查找树,Trie树,是一种树形结构,典型应用是用于统计,排序和保存大量的字符串,所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来节约存储空间...
  • 01trie树

    2021-09-10 19:52:06
    01trie树顾名思义,是trie的一种特殊形式,树上只有0和1两种值,主要用于解决点与点甚至是区间的异或和最大、最小问题。 建树插入数字的时候和普通的trie树一模一样,而求一个数x与树上所有数的异或最大值时主要是...
  • #include<iostream> #include<vector> #include<...typedef struct TrieTree* Position; enum Color{red,black}; struct TrieTree { char ch; Color color;//red表示一个单词到此处结束,
  • 原理: Trie树和其他的数据结构一样,支持查找、插入以及删除操作,当然也可以添加其他的操作。Trie树的编程非常的简单,这一切都得益于其优秀的性质。Trie树和其他的各种查找树一样也是由链接的节点组成的数据结构...
  • Hash树Trie树详解及其应用

    千次阅读 2016-08-19 15:02:15
     字典Trie)可以保存一些字符串->值的对应关系。基本上,它跟 Java 的 HashMap 功能相同,都是 key-value 映射,只不过 Trie 的 key 只能是字符串。  Trie 的强大之处就在于它的时间复杂度。它的插入和
  • Trie树,插入,查找,删除,遍历

    千次阅读 2018-09-12 21:54:41
    Trie树的结构如下: 就根据这个图来建立就好了。 就是删除要考虑几种情况: 1.删除中间的红点 2.删除末红点找到前面的支点(如上图,要删除bcd,就要找到b指的节点,再向下删除,像abd,就要从ab指的节点删掉...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 9,813
精华内容 3,925
关键字:

trie树删除