字典树
简介:字典树,又称单词查找树,Trie树,是一种树形结构,是哈希树的变种。
优点:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较。
性质:根节点不包含字符,除根节点外每一个节点都只包含一个字符; 从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串; 每个节点的所有子节点包含的字符都不相同。
操作:
记trie[i][j]表示第i个节点的第j个儿子为哪个节点,tot为总的节点个数
插入:
void insert() { int len = strlen(s); int rt = 0; for (int i = 0; i < len; i++) { int id = s[i] - 'a'; if(!trie[rt][id])trie[rt][id] = ++tot; rt = trie[rt][id]; // sum[rt]++; } //vis[rt] = true; }
查询:
①如果查询的是某个单词是否出现,可以开一个bool类型的数组vis[i]表示第i个节点是否为单词的结尾
②如果查询的是某个前缀出现了多少次,可以开一个int类型的数组sum[i]表示以第i个节点为结尾的前缀出现的次数
int find() { int len = strlen(s); int rt = 0; for (int i = 0; i < len; i++) { int id = s[i] - 'a'; if(!trie[rt][id]) return 0; rt = trie[rt][id]; } return sum[rt];//或者vis[rt] }
清空:每次新开一个节点,将他的儿子都清空(对应多组,每组加起来不超过某个值的情况,不能每次都memset)。
指针版:
struct node { int cnt; node *next[26]; node() { cnt = 0; memset(next, 0, sizeof(next)); } }; node *rt; void init() { rt = new node(); } void Insert() { int len = strlen(s); node *p = rt; for (int i = 0; i < len; i++) { int id = s[i] - 'a'; if(p -> next[id] == NULL) p -> next[id] = new node(); p = p -> next[id]; p -> cnt ++; } } int Find() { int len = strlen(s); node *p = rt; for (int i = 0; i < len; i++) { int id = s[i] - 'a'; if(p -> next[id] == NULL) return 0; p = p -> next[id]; } return p -> cnt; }
例题1:hdu 1251
代码:
#include<bits/stdc++.h> using namespace std; #define LL long long #define pb push_back #define mem(a, b) memset(a, b, sizeof(a)) const int N = 5e5 + 5; int trie[N][26], sum[N], tot = 0; char s[55]; void Insert(int len) { int rt = 0; for (int i = 0; i < len; i++) { int id = s[i] - 'a'; if(!trie[rt][id])trie[rt][id] = ++tot; rt = trie[rt][id]; sum[rt]++; } } int Find(int len) { int rt = 0; for (int i = 0; i < len; i++) { int id = s[i] - 'a'; //cout << s[i] << id <<endl; if(!trie[rt][id]) return 0; rt = trie[rt][id]; } return sum[rt]; } int main() { int tot = 0; while(~ scanf("%c", &s[tot++])) { if(s[tot - 1] == ' ') { if(tot == 1) break; else { Insert(tot - 1); tot = 0; } } } tot = 0; while(~ scanf("%c", &s[tot++])) { if(s[tot - 1] == ' ') { printf("%d ", Find(tot - 1)); tot = 0; } } return 0; }
#include<bits/stdc++.h> using namespace std; #define LL long long #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) const int N=5e5+5; int trie[N][26]; int sum[N]; int tot=0; char s[15]; void insert(){ int len=strlen(s); int root=0; for(int i=0;i<len;i++){ int id=s[i]-'a'; if(!trie[root][id])trie[root][id]=++tot; root=trie[root][id]; sum[root]++; } } int find(){ int len=strlen(s); int root=0; for(int i=0;i<len;i++){ int id=s[i]-'a'; if(!trie[root][id])return 0; root=trie[root][id]; } return sum[root]; } int main(){ while(gets(s)!=NULL){ if(s[0]=='