又称单词查找树,trie树,是一种树形结构,是一种哈希树的变种。典型应用是用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。浅谈trie树

(以上内容摘自百度百科)

  trie树是一种ennnnnnn树,2333333,本弱的表达能力真的是很弱额。那trie树是用来干什么的那?做题的trie树把字符存到节点里,如上所说,他利用字符串的公共前缀节省查询时间。这也说明了trie树的存储方式是对于不同字符串的相同前缀,他们共用一些相同的节点。比如:abcd和abdd,在存abcd的时候发现0号节点(trie树的根节点,用于把首字母就不同的字符串连接起来)没有a这个儿子,就新建一个a,依次往下建,建出一条链,a->b->c->d,然后在建abdd的时候发现0号节点有a这个儿子了,就不在建了,而是 直接跳到a那里,在往下发现a又有b这个儿子了,还是直接跳过去,然后发现b没有d这个儿子,所以新建一个d,然后d又建一个儿子是d。这就是trie树的建树机制啦。上面的例子建出来的树长下面的样子

   浅谈trie树

  而具体实现就是用数字来代表字符,开一个数组或者把所有都封装到一个结构体里来表示trie树就可以了。

来看一道模板题https://www.luogu.org/problemnew/show/P1481

风之子刚走进他的考场,就……

花花:当当当当~~偶是魅力女皇——花花!!^^(华丽出场,礼炮,鲜花)

风之子:我呕……(杀死人的眼神)快说题目!否则……-_-###

花花:……咦好冷我们现在要解决的是魔族的密码问题(自我陶醉:搞不好魔族里面还会有人用密码给我和菜虫写情书咧,哦活活,当然是给我的比较多拉*^_^*)。魔族现在使用一种新型的密码系统。每一个密码都是一个给定的仅包含小写字母的英文单词表,每个单词至少包含1个字母,至多75个字母。如果在一个由一个词或多个词组成的表中,除了最后一个以外,每个单词都被其后的一个单词所包含,即前一个单词是后一个单词的前缀,则称词表为一个词链。例如下面单词组成了一个词链:

i int integer

但下面的单词不组成词链:

integer

intern 现在你要做的就是在一个给定的单词表中取出一些词,组成最长的词链,就是包含单词数最多的词链。将它的单词数统计出来,就得到密码了。

风之子:密码就是最长词链所包括的单词数阿……

花花:活活活,还有,看你长得还不错,给你一个样例吧:

输入格式:

这些文件的格式是,第一行为单词表中的单词数N(1<=N<=2000),下面每一行有一个单词,按字典顺序排列,中间也没有重复的单词咧!!

输出格式:

你要提交的文件中只要在第一行输出密码就行啦^^

 

  很显然,答案就是包含单词最多的单词包含了多少单词,并且除它本身外 ,其他单词都得是它的前缀才算被他包含。一眼想到trie树嘛,每个单词插入trie树,在结束的位置记录一下这个位置的点是一个结束位置,但是因为要求的是包含其他单词最多的单词包含了多少单词,所以不只是要在这里记录一下,从这个位置往下的每一个节点都要加一个单词,浅谈trie树

就是这里以1节点结尾的单词,包含在以2,3,4结尾的单词里。这个在建完树后加一个dfs处理一遍就好了。

代码:

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 int tree[2005][2005];
 6 int tot;
 7 int n; 
 8 int ans;
 9 int end[2005];//记录以被以节点i结尾的单词包含的单词有多少个,当然如果没有以节点i为结尾的单词也还是要记录的,因为下面的节点需要用,所以最后统计的时候只统计叶子节点(也就是最长的那些单词就好了),但是由于是取max,都统计一遍也不会出错 
10 string s;
11 void insert()//插入单词 
12 {
13     int len=s.length();
14     int now=0;
15     for(int i=0;i<len;++i)//从根节点开始 
16     {
17         int p=s[i];
18         if(!tree[now][p])tree[now][p]=++tot;//如果没有这个节点,就新建一个 
19         now=tree[now][p];//此时肯定是有这个儿子节点的,所以直接跳过去 
20     }
21     end[now]++;//以now为结尾的单词数+1 
22 }
23 void dfs(int x)
24 {
25     for(int i=0;i<=2000;++i)
26         if(tree[x][i])
27         {
28             end[tree[x][i]]+=end[x];
29             dfs(tree[x][i]); 
30         }
31 }
32 int main()
33 {
34     scanf("%d",&n);
35     for(int i=1;i<=n;++i)
36     {
37         cin>>s;
38         insert();
39     }
40     dfs(0);
41     for(int i=0;i<=2000;++i)ans=max(ans,end[i]);
42     printf("%d",ans);
43     return 0;
44 }
View Code

相关文章:

  • 2021-06-12
  • 2021-11-12
  • 2021-08-04
  • 2022-12-23
  • 2021-10-31
  • 2021-05-20
猜你喜欢
  • 2021-12-16
  • 2021-10-31
  • 2021-09-01
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案