trie树:一种基于前缀存储的高效树型结构
trie树的引入:现给出一个具有n个单词的词典,然后进行q次询问,每次询问给出一单词,平均长度是L,问这个单词是否出现在之前的词典中
暴力枚举的话,从头到尾依次扫描与他相同的单词,复杂度为o(n*q*l)
想想平时我们查字典的方式的话,只需要l次比较即可!
基于上述“查字典”的方式,建立的数据结构,就是trie;字典树
trie树,又叫单词前缀树,字典树,是一种用于快速检索的多叉树结构;
核心思想用空间换时间,利用字符串的公共前缀,来最大限度的减少无谓的字符串比较,进而降低时间复杂度
基本性质:1.根节点不包含字符,除根节点外,每一条边对应一个字符
2.从根节点到某个节点,将边上的字符连起来,会得到该字符对应的前缀
3.每个节点对应的前缀都不相同
模板:
1静态数组:
int a[2000][27],tot=1,end_[2000]; void insert(char *s) { int p=0,len=strlen(s); for(int i=0;i<lem;i++) { int t=s[i]-'a'; if(trie[p][t]==0) trie[p][t]=tot++; p=trie[p][t]; } end_[p]=1; } int query(char *s) { int p=0,len=strlen(s); for(int i=0;i<len;i++) { int t=s[i]-'a'; if(trie[p][t]==0) return 0; p=trie[p][t]; } if(end_[p]) return 1; else return 0; }
2.动态指针
struct trie{ trie *next[27];bool last; trie(){ memset(next,0,sizeof(next)); last=false; } }; trie *root; void init(){ root=new trie; } void insert(char *s) { int len=strlen(s);trie *p=root; for(int i=0;i<len;i++) { int t=s[i]-'a'; if(p->next[t]==0) p->next[t]=new trie; p=p->next[t]; } p->last=true; } int query(char *s) { trie *p=root;int len=strlen(s); for(int i=0;i<len;i++) { int t=s[i]-'a'; if(p->next[t]==0) return 0; p=p->next[t]; } if(p->last) return 1; else return 0; } void deltrie(trie *t) { for(int i=0;i<27;i++) if(t->next[t]) deltrie(t->next[t]); delete t; }