• HDU1251 统计难题[map的应用][Trie树]


    一、题意

    给出一组单词,另给出一组单词用作查询,求解对于每个用于查询的单词,前一组中有多少个单词以其为前缀。

    二、分析

    根据题目很容易想到hash的方法,首先可以朴素的考虑将第一组中的所有单词的前缀利用map进行统计,查询时直接得到结果

    所以很容易可以得到以下代码。

    注意:输入时的空行代表第一行的结束,利用gets读入并根据字符串的长度是否为0来判断;

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 # include <map>
     5 using namespace std;
     6 const int maxn = 15;
     7 char word[maxn];
     8 map<string,int> M;
     9 int main()
    10 {
    11     while(gets(word))
    12     {
    13         if(strlen(word) == 0)
    14             break;
    15         int L = strlen(word);
    16         for(int i=L;i>0;i--)
    17         {
    18             word[i] = '';
    19             M[word]++;
    20         }
    21     }
    22     while(gets(word))
    23         printf("%d
    ",M[word]);
    24     return 0;
    25 }
    View Code

     然而,有些题目会卡map的用法,需要找到更高效的算法,这里可以使用Trie树,也就是前缀树、字典树来解决问题。

    字典树的根节点为空,用边来表示字母,用根节点到某个节点的路径表示一个单词,字典树可以用数组表示,其中Tree[root][i]=k表示树上位置标号为root的节点的第i个子节点的位置编号为k

     1 # include <iostream>
     2 # include <cstdio>
     3 # include <cstring>
     4 using namespace std;
     5 const int maxn = 2e6+5;
     6 int Tree[maxn][30],sum[maxn];
     7 int cnt;
     8 void Insert(char word[])
     9 {
    10     int L = strlen(word);
    11     int root = 0;
    12     for(int i=0;i<L;i++)
    13     {
    14         int id = word[i] - 'a';
    15         if(!Tree[root][id])
    16             Tree[root][id] = ++cnt;
    17         sum[Tree[root][id]]++;
    18         root = Tree[root][id];
    19     }
    20 }
    21 int Find(char word[])
    22 {
    23     int L = strlen(word);
    24     int root = 0;
    25     for(int i=0;i<L;i++)
    26     {
    27         int id = word[i] - 'a';
    28         if(!Tree[root][id])
    29             return 0;
    30         root = Tree[root][id];
    31     }
    32     return sum[root];
    33 }
    34 int main()
    35 {
    36     char word[15];
    37     cnt = 0;
    38     while(gets(word))
    39     {
    40         if(strlen(word) == 0)
    41             break;
    42         Insert(word);
    43     }    
    44     while(scanf("%s",word)!=EOF)
    45         printf("%d
    ",Find(word));
    46     return 0;
    47 }
    View Code

    注意,如果第二组单词用scan读入记得写!=EOF的形式

  • 相关阅读:
    Installshield制作安装程序
    vista以上系统中开发的程序以管理员权限运行
    检查当前系统版本是否为Vista或更高的版本
    在程序运行过程中调用另一个程序
    Spin Control(旋转按钮控件、上下微调按钮控件)
    因改变工具栏图标导致菜单栏高度随之变大的解决方案
    Unicode环境下的字符差异
    注册表API
    文件的读写操作
    const char* 和 char* const
  • 原文地址:https://www.cnblogs.com/cnXuYang/p/10280268.html
Copyright © 2020-2023  润新知