zoukankan      html  css  js  c++  java
  • 字典树(Trie树)

    字典树(Trie Tree)

    入门模板题 hdu oj P1251

    题目

      Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).

    输入格式

      输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

      注意:本题只有一组测试数据,处理到文件结束.

    输出格式

      对于每个提问,给出以该字符串为前缀的单词的数量.

    输入样例

    banana
    band
    bee
    absolute
    acm
     
     
    ba
    b
    band
    abc

    输出样例

    2
    3
    1
    0

      前不久学的Trie树,主要参考自这个巨佬的博客:Trie树傻瓜式入门+板子+经典例题

      乱写一通笔记。

      Trie树也叫字典树,又称单词查找树,是一种树形的数据结构,是哈希树的变种。主要运用于统计、排序和保存大量的字符串(但不仅限于字符串)。

      它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。

      

      它主要长这样:

      (下图为插入了字符串at、bee、ben、bt、q后的Trie树)

      

      从这幅图里可以看出,Trie树的根节点是不包括字符的。也可以看出Trie树的主要思想。

      代码(结合hduoj的例题使用):

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <string>
    using namespace std;
    
    const int maxn=1e6+10;
    
    char s[maxn];
    
    struct Trie{
        int next[27];
        int cnt;
        void init(){
            cnt=0;
            memset(next,-1,sizeof next);
        }
    }node[maxn];
    int qwq=1;
    
    void Insert(string s){
        int p=0;
        for (int i=0;i<s.size();i++){
            int temp=s[i]-'a';
            if (node[p].next[temp]==-1){    //不存在该节点,则新建节点 
                node[qwq].init();
                node[p].next[temp]=qwq;
                qwq++;    //后移一位,指向下一个未知的节点 
            }
            p=node[p].next[temp];    //向下走,走到目前搜到的最后一个节点 
            node[p].cnt++;
        }
    }
    
    void query(string s){    //查询 
        int p=0;
        for (int i=0;i<s.size();i++){
            int temp=s[i]-'a';
            if (node[p].next[temp]==-1){    //不存在具有该前缀的字符串 
                printf("0
    ");
                return ;
            }
            p=node[p].next[temp];
        }
        printf("%d
    ",node[p].cnt);
    }
    
    int main(){
    //    freopen("test1.in","r",stdin);
        node[0].init();
        string s;
        while (getline(cin,s))
            if (s.size()==0)    break;
            else Insert(s);
        while (getline(cin,s))
            query(s);
        return 0;
    }

    [学习自百度百科和其他网络资料]

  • 相关阅读:
    树形dp--P2014 [CTSC1997]选课
    背包变形--P1759 通天之潜水
    区间dp--P1880 [NOI1995]石子合并
    动态规划--P2758 编辑距离
    筛法--CF449C Jzzhu and Apples
    BZOJ3998: [TJOI2015]弦论(后缀自动机,Parent树)
    BZOJ3530: [Sdoi2014]数数(Trie图,数位Dp)
    BZOJ1444: [Jsoi2009]有趣的游戏(Trie图,矩乘)
    BZOJ1195: [HNOI2006]最短母串(Trie图,搜索)
    BZOJ3238: [Ahoi2013]差异(后缀数组)
  • 原文地址:https://www.cnblogs.com/awakening-orz/p/10678500.html
Copyright © 2011-2022 走看看