字典树的建立和基本查找
字典树的建立和基本查找
一.字典树的定义
字典树又叫做前缀树,任意一个或多个字符串可以构建一棵字典树用于存储多个串的公共前缀
二.构建字典树的两种方法
(1)字典树的链表构建及查找
在用链表构造的字典树中每一个节点有着一个数据域来存放该点代表的字符和26个指针分别指向a(A)~z(Z)26个可能出现的子字符,在寻找某个字符串是否出现时,从根节点出发不断向下查找配对,如果到了最后一个字符都存在则表示该前缀存在
(2)字典树的二维数组构建及查找
用二维数组tree[i][j]来标识一颗字典树,其中i为父节点,j为子节点,程序开始时父节点为root节点。tree[i][j]表示节点i第j个儿子的编号【这里我们规定root的编号为0】
1) 字典树的二维数组构建
2)字典树的二维数组查找
三.代码模板
(1) 字典树的链表模板
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const int SIZE=10; 2 struct Trie 3 { 4 int count;//前缀出现的次数 5 struct Trie *next[SIZE];//孩子节点的数目 6 bool isEnd; //判断到这个位置是否是一个单词 7 string name; 8 Trie()//构造函数 9 { 10 count=0; 11 memset(next,0,sizeof(next)); 12 isEnd=false; 13 } 14 }; 15 struct Trie *root=new Trie;//建立根节点 16 void Insert(string s) 17 { 18 int len=s.length(); 19 int pos; 20 struct Trie *u=root; 21 for(int i=0;inext[pos]==NULL)//数字在边上,或者说是以位置的方式体现,不需要存储 22 u->next[pos]=new Trie; 23 u=u->next[pos]; 24 u->count++; 25 } 26 u->isEnd=true;//表明为一个单词的节点 27 u->name=s;//同时存储单词 28 } 29 int Search(string s) 30 { 31 struct Trie *u=root; 32 int len=s.length(); 33 for(int i=0;inext[pos]==NULL) 34 return 0; 35 else 36 u=u->next[pos]; 37 } 38 return u->count; 39 }
(2) 字典树的二维数组模板
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const int maxn =2e6+5;//如果是64MB可以开到2e6+5,尽量开大 2 int tree[maxn][30];//tree[i][j]表示节点i的第j个儿子的节点编号 3 bool flagg[maxn];//表示以该节点结尾是一个单词 4 int tot;//总节点数 5 void insert_(char *str) 6 { 7 int len=strlen(str); 8 int root=0; 9 for(int i=0;i<len;i++) 10 { 11 int id=str[i]-'0'; 12 if(!tree[root][id]) tree[root][id]=++tot; 13 root=tree[root][id]; 14 } 15 flagg[root]=true; 16 } 17 bool find_(char *str)//查询操作,按具体要求改动 18 { 19 int len=strlen(str); 20 int root=0; 21 for(int i=0;i<len;i++) 22 { 23 int id=str[i]-'0'; 24 if(!tree[root][id]) return false; 25 root=tree[root][id]; 26 } 27 return true; 28 } 29 void init()//最后清空,节省时间 30 { 31 for(int i=0;i<=tot;i++) 32 { 33 flagg[i]=false; 34 for(int j=0;j<10;j++) 35 tree[i][j]=0; 36 } 37 tot=0; 38 }