字典树

一世执手 提交于 2019-11-27 04:43:40

字典树概念

是一种树形结构
Trie树的基本性质可以归纳为:

(1) 根节点不包括字符,除根节点意外每个节点只包含一个字符

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

(3) 每个节点的所有子节点包含的字符串不相同

当然,Trie树也有一个缺点,如果系统中存在大量字符串且这些字符串基本没有公共前缀,则相应的trie树将非常消耗内存
利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

基本操作有:查找插入删除

应用

  • 字符串检索
  • 字符串公共前缀
  • 排序
  • 后缀树,AC自动机

字典树的储存:利用二维数组

如果用一位数组表示,时26^n空间复杂度,如果用二维数组表示,是26*n的空间复杂度,查询时间复杂度为O(1);
对于单个字符tree[root][id];root 表示这个字母在单词的第几项,id表示这个字母的在字母表里的下标
如对于acb
1000
0020
0300
数字表示顺序
对于
1000
0234
0000
表示
ab
ac
ad
sum[1]=3
sum[2]=1;
sum[3]=1;
sum[4]=1;
如果前缀都是一样的话没有问题,但前缀不一样时
对于
ac
cb
103
002
000
040
原来3应该在i=2这一行的j=2,但cb是一个新的数,所以c在第一行

总结

tree[i][j]=z;i轴就是树的深度,j表示字符在字母的下标;z表示顺序
所以得出结论,sum[x]表示的是x的结点数,可以认为以x为子字符串,的字符的个数
对于i=0时,出现了几个数,表示有几个数

例题:

第一题:

HDU1251统计出以某个字符串为前缀的单词数量,先把输入的字符串以字典树的形式插入到二维数组,再用sum去记录子节点数

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
const int maxn =2e6+5;
int tree[maxn][30];
int sum[maxn];
int tot;
//字典树的插入
void insert_(char *str){
   int  len=strlen(str);
   int root=0;
   for(int i=0;i<len;i++){
       int id=str[i]-'a';//把字母用数字表示,方便sum的统计
       if(!tree[root][id]) tree[root][id]=++tot;//这个字母存过,不变化
       sum[tree[root][id]]++;//记录节点访问次数
       root=tree[root][id];
   }
   //root在此对应某个单词,一一对应
}
//字典树的查找
int find_(char *str){
    int len=strlen(str);
    int root=0;//初始为0是对于第一个字母肯定在第一行
    for(int i=0;i<len;i++){
        int id=str[i]-'a';
        if(!tree[root][id]) return 0;//如果为空,表示字典里没有这个字符
        root=tree[root][id];//之后的肯定不会在第一行,tot的值就是他所在的i位置
    }
    return sum[root];//返回当前字符串结尾节点的访问次数,也就是作为前缀的出现次数
}
int main(){
    char ss[maxn];
    tot=0;//表示从第一个字母开始,后面的字母的id
    //memset(tree,0,sizeof(tree));全局静态变量,初始值为0,本题只进行一次操作,所以不用初始化
    while(gets(ss)){
        if(ss[0]=='\0') break;//输入为空时
        insert_(ss);
    }
    while(scanf("%s",ss)!=EOF){
        printf("%d\n",find_(ss));
    }


    return 0;
}

HDU2072统计不同单词数

思路:利用字典树记录每个字母,字母之间进行标记
https://blog.csdn.net/qq_38891827/article/details/80532462

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!