字典树专题

一、模板

数组版的:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define maxn 500050
 4 char str[50010][100];
 5 int nxt;
 6 struct node
 7 {
 8     int val;
 9     int next[26];
10 }tree[maxn];
11 //将结构体改成数组更容易初始化,treenext[maxn][26],treeval[maxn]
12 int add()
13 {
14     memset(&tree[nxt],0,sizeof(node));
15     return nxt++;
16 }
17 void insert(char *s)
18 {
19     int rt=0,len=strlen(s);
20     for(int i=0;i<len;i++)
21     {
22         int c=s[i]-‘a‘;
23         if(!tree[rt].next[c])
24         {
25             tree[rt].next[c]=add();
26         }
27         rt=tree[rt].next[c];
28     }
29     tree[rt].val++;
30 }
31 int query(char *s){
32     int rt=0, len = strlen(s);
33     int id=-1;
34     for(int i=0; i<len; i++){
35         int c=s[i]-‘0‘;
36         if(!tree[rt].next[c]) return -1;
37         rt=tree[rt].next[c];
38         id = tree[rt].val;
39     }
40     return id;
41 }
42 int main()
43 {
44     int l=0;
45     nxt=1;
46     while(scanf("%s",str[l])!=EOF)
47     {
48         insert(str[l]);
49         l++;
50     }
51     for(int i=0;i<l;i++)
52     {
53         printf("%d\n",query(str[i]));
54     }
55     return 0;
56 }

指针版的:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 char c[100][100];
 5 const int MAX=10;
 6 typedef struct Node
 7 {
 8     int val;
 9     struct Node *next[MAX];
10 }TrieNode;
11
12 TrieNode *head;
13
14 void insert(char str[], int id)
15 {
16     Node *t,*s=head;
17     int len=strlen(str);
18     for(int i=0;i<len;i++)
19     {
20         int c=str[i]-‘0‘;
21         if(s->next[c]==NULL)
22         {
23             t=new Node;
24             for(int j=0;j<10;j++) t->next[j]=NULL;
25             t->val=-1;
26             s->next[c]=t;
27         }
28         s=s->next[c];
29         if(s->val<0) s->val=id;
30     }
31 }
32
33 int query(char str[])
34 {
35     Node *s=head;
36     int ans;
37     int len=strlen(str);
38     for(int i=0;i<len;i++)
39     {
40         int c=str[i]-‘0‘;
41         if(s->next[c]==NULL) return -1;
42         s=s->next[c];
43         ans=s->val;
44     }
45     return ans;
46 }
47
48 void Tree_Del(Node *p)
49 {
50     for(int i=0;i<10;i++)
51     {
52         if(p->next[i]!=NULL)
53           Tree_Del(p->next[i]);
54     }
55     free(p);
56 }
57
58 int main()
59 {
60     head=new Node;
61     for(int i=0;i<10;i++)head->next[i]=NULL;
62     head->val=-1;
63     int n, m;
64     char str[60];
65     scanf("%d%d",&n, &m);
66     for(int i=0; i<n; i++)
67     {
68         scanf("%s",str);
69         insert(str, i);
70     }
71     for(int i=0; i<m; i++){
72         scanf("%s", str);
73         printf("%d\n", query(str));//输出字符串是在第几次出现过
74     }
75     Tree_Del(head);//释放空间,防止超内存
76     return 0;
77 }

二、题目

1、【HDU 4099】Revenge of Fibonacci

题意:给出斐波那契数列的前k位,k不超过40,找出最小的正整数n,满足F(n)的前k位与给定数的前k位相同,斐波那契数列的项数不超过100000。

解题思路:本题可以分为两步:

第一步就是预处理出100000项斐波那契数列的前40位,插入到字典树中。

第二步就是查询匹配求最小的n。

对于第一步,我们可以把斐波那契数列精确到50多位,然后只存40位即可,这样就防止进位的误差。在斐波那契数列加法过程中,我们只把它的前50多位进行相加,不然存不下。

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #include <cstring>
 5 #include <string>
 6 using namespace std;
 7 const int N=1e6+10;
 8 char f[5][100], str[100];
 9 void add(char *a, char *b, char *c){
10     int lena=strlen(a), lenb=strlen(b);
11     int lenc=0, tmp=0;
12     while(1){
13         if(lena==0 && lenb==0) break;
14         if(lena==0){
15             int sum=b[--lenb]-‘0‘+tmp;
16             c[lenc++] = sum%10+‘0‘;
17             tmp = sum/10;
18         }
19         else{
20             int sum=b[--lenb]-‘0‘+a[--lena]-‘0‘+tmp;
21             c[lenc++] = sum%10+‘0‘;
22             tmp = sum/10;
23         }
24     }
25     if(tmp) c[lenc++]=tmp+‘0‘;
26     strcpy(a, b);
27     for(int j=0; j<lenc; j++){
28         b[j] = c[lenc-j-1];
29     }
30     b[lenc]=‘\0‘;
31 }
32 int nxt;
33 struct node{
34     int val, next[10];
35 }tree[7*N];
36 int add()
37 {
38     memset(&tree[nxt],0,sizeof(node));
39     return nxt++;
40 }
41
42 void insert(char *s, int id)
43 {
44     int rt=0,len=strlen(s);
45     for(int i=0;i<min(len, 41);i++)
46     {
47         int c=s[i]-‘0‘;
48         if(!tree[rt].next[c])
49         {
50             tree[rt].next[c]=add();
51             tree[tree[rt].next[c]].val=id;
52         }
53         rt=tree[rt].next[c];
54     }
55 }
56
57 int query(char *s){
58     int rt=0, len = strlen(s);
59     int id=-1;
60     for(int i=0; i<len; i++){
61         int c=s[i]-‘0‘;
62         if(!tree[rt].next[c]) return -1;
63         rt=tree[rt].next[c];
64         id = tree[rt].val;
65     }
66     return id;
67 }
68 int main(){
69     nxt = 1;
70     f[0][0]=‘1‘, f[1][0]=‘1‘;
71     insert(f[0], 0);
72     for(int i=2; i<100000; i++){
73         int len=strlen(f[0]), llen=strlen(f[1]);
74         if(llen>60){
75             f[1][llen-1]=‘\0‘;
76             f[0][len-1]=‘\0‘;
77         }
78         add(f[0], f[1], f[3]);
79         insert(f[1], i);
80     }
81     int t, cas=1;
82     scanf("%d", &t);
83     while(t--){
84         scanf("%s", str);
85         int flag = query(str);
86         printf("Case #%d: %d\n", cas++, flag);
87     }
88     return 0;
89 }

时间: 2025-01-12 03:36:34

字典树专题的相关文章

(字典树)How many--hdu--2609

http://acm.hdu.edu.cn/showproblem.php?pid=2609 How many Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1707    Accepted Submission(s): 693 Problem Description Give you n ( n < 10000) necklaces

hdu 1251 统计难题(字典树)

Problem Description Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀). Input 输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串. 注意:本题只有一组测试数据,处理到文件结束. Output 对于每个提

51nod round3# 序列分解(折半枚举+字典树)

小刀和大刀是双胞胎兄弟.今天他们玩一个有意思的游戏. 大刀给小刀准备了一个长度为n的整数序列.小刀试着把这个序列分解成两个长度为n/2的子序列. 这两个子序列必须满足以下两个条件: 1.他们不能相互重叠. 2.他们要完全一样. 如果小刀可以分解成功,大刀会给小刀一些糖果. 然而这个问题对于小刀来说太难了.他想请你来帮忙. Input 第一行给出一个T,表示T组数据.(1<=T<=5) 接下来每一组数据,输入共2行. 第一行包含一个整数n (2<=n<=40且为偶数). 第二行给出n

白话算法与数据结构之【字典树】

1. 什么是trie树 1.Trie树 (特例结构树) Trie树,又称单词查找树.字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树结构.典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计.它的优点是:最大限度地减少无谓的字符串比较,查询效率比哈希表高.      Trie的核心思想是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. Trie树也有它的缺点,Trie树的内存消耗非常大.当然,或许用左儿子

[算法系列之二十]字典树(Trie)

一 概述 又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种.典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 二 优点 利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希表高. 三 性质 (1)根节点不包含字符,除根节点外每一个节点都只包含一个字符: (2)从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串: (3)每个节点的所有子节点包含的字符都不相同. 单词列表为"apps&

poj 3764 The xor-longest Path(字典树)

题目链接:poj 3764 The xor-longest Path 题目大意:给定一棵树,每条边上有一个权值,找出一条路径,使得路径上权值的亦或和最大. 解题思路:dfs一遍,预处理出每个节点到根节点路径的亦或和rec,那么任意路径均可以表示rec[a] ^ rec[b],所以问题 就转换成在一些数中选出两个数亦或和最大,那么就建立字典树查询即可. #include <cstdio> #include <cstring> #include <algorithm> us

字典树

字典树(Trie)是一种很特别的树状信息检索数据结构,如同其名,它的构成就像一本字典,可以让你快速的进行字符插入.字符串搜索等. Trie 一词来自 retrieval,发音为 /tri:/ "tree",也有人读为 /tra?/ "try". 字典树设计的核心思想是空间换时间,所以数据结构本身比较消耗空间.但它利用了字符串的共同前缀(Common Prefix)作为存储依据,以此来节省存储空间,并加速搜索时间.Trie 的字符串搜索时间复杂度为 O(m),m 为最

字典树的简单实现

Trie树,又称为字典树,是一种树形结构,是一种哈希树的变种,是一种用于快速检索的多叉树数据结构. 用于保存大量的字符串.它的优点是:利用字符串的公共前缀来节约存储空间. Trie的核心思想是空间换时间.利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的. 它有3个基本性质: 1.根节点不包含字符,除根节点外每一个节点都只包含一个字符. 2.从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串. 3.每个节点的所有子节点包含的字符都不相同. 搜索字典项目的方法为: (1)

跳跃表,字典树(单词查找树,Trie树),后缀树,KMP算法,AC 自动机相关算法原理详细汇总

第一部分:跳跃表 本文将总结一种数据结构:跳跃表.前半部分跳跃表性质和操作的介绍直接摘自<让算法的效率跳起来--浅谈"跳跃表"的相关操作及其应用>上海市华东师范大学第二附属中学 魏冉.之后将附上跳跃表的源代码,以及本人对其的了解.难免有错误之处,希望指正,共同进步.谢谢. 跳跃表(Skip List)是1987年才诞生的一种崭新的数据结构,它在进行查找.插入.删除等操作时的期望时间复杂度均为O(logn),有着近乎替代平衡树的本领.而且最重要的一点,就是它的编程复杂度较同类