hdu 1251:统计难题[【trie树】||【map】

<题目链接>

                                       统计难题

Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.
注意:本题只有一组测试数据,处理到文件结束.
 
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
 
Sample Input
banana
band
bee
absolute
acm
 
ba
b
band
abc
 
Sample Output
2
3
1
0
 
tire树指针实现:
 1 #include <cstdio>
 2 #include <malloc.h>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 char s[15];
 8 struct node{
 9     int cnt;
10     node *next[26];  //该节点的所有子节点
11     void init(){   //初始化该节点
12         cnt=0;
13         for(int i=0;i<26;i++)
14             next[i]=NULL;
15     }
16 };
17 void insert(node *root,char *s){
18     node *p =root ,*now;
19     for(int i=0;s[i];i++){
20         int tmp=s[i]-'a';
21         if(p->next[tmp]==NULL){   //如果该节点为空,则创建一个新的节点
22             p->next[tmp]=new node;
23             p=p->next[tmp];
24             p->init();
25         }
26         else p=p->next[tmp];   //如果该节点不空,则继续向下插入
27         p->cnt++;    //以该节点结尾的前缀个数+1
28     }
29 }
30 int find(node *root,char *s){
31     node *p=root;
32     for(int i=0;s[i];i++){
33         int tmp=s[i]-'a';
34         p=p->next[tmp];
35         if(!p)return 0;   //如果遇到不满足的节点,就直接结束
36     }
37     return p->cnt;
38 }
39 int main(){
40     node *root=new node;
41     root->init();
42     while(gets(s)&&strlen(s))
43         insert(root,s);
44     while(gets(s))
45         printf("%d
",find(root,s));
46     return 0;
47 }

trie树数组实现:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 const int N = 1e6+10;
 7 int trie[N][26];     //trie[now][next]代表第一次遍历到该节点的序号
 8 int num[N]={0},pos=0;
 9 void Insert(char *str){
10     int now=0;
11     for(int i=0;str[i];i++){
12         int next=str[i]-'a';
13         if(!trie[now][next])trie[now][next]=++pos;  //如果没有遍历过该节点,就给该节点赋值(相当于给trie树创建一个节点)
14         now=trie[now][next];     
15         num[now]++;    //该前缀的数量+1
16     }
17 }
18 int Search(char *str){
19     int now=0;
20     for(int i=0;str[i];i++){
21         int next=str[i]-'a';
22         if(!trie[now][next])return 0;   //只要一找到不符合的节点,就直接返回0
23         now=trie[now][next];   //当前节点继续向下匹配
24     }
25     return num[now];
26 }
27 int main(){
28     char str[15];
29     while(gets(str)&&strlen(str))
30         Insert(str);
31     while(gets(str))
32         printf("%d
",Search(str));
33     return 0;
34 }

map做法

#include <cstdio>
#include <string>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;


int main()
{
    string s, str[10000];
    int cur = 0;
    map<string, int>mapp;
    while (getline(cin, s) && s[0] != '')    //注意是用这个来判断空行,首先一定要用getline读入,其次是s[0]==''时表示是空行
    {
        string ss;
        for (int i = 1; i <=s.length(); i++) {
            ss = s.substr(0, i);         //获得字符串s中从第0位开始的长度为i的字符串
            mapp[ss]++;
        }
    }
    while (cin >> s)
    {
        printf("%d
", mapp[s]);
    }
    return 0;
}
 
2018-04-08
原文地址:https://www.cnblogs.com/00isok/p/8736794.html