HDU 1251 统计难题 (字典树模板题)

来源:互联网 发布:oracle数据导出导入 编辑:程序博客网 时间:2024/06/01 21:57


统计难题

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131070/65535 K (Java/Others)
Total Submission(s): 42355    Accepted Submission(s): 15233


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

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

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

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

Sample Input
bananabandbeeabsoluteacmbabbandabc
 

Sample Output
2310
 

Author
Ignatius.L
 

Recommend
Ignatius.L

两种模板, 链表模板好理解, 数组模板快,链表模板忘记清空就会MLE

数组模板:

#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>const int maxn = 1e6 + 7;int id, ch[maxn][30], cnt[maxn];char str[15];void Insert(char *s){    int rt = 0;    int len = strlen(s);    for(int i = 0; i < len; i++)    {        if(!ch[rt][s[i]-'a'])        {            memset(ch[id], 0, sizeof(ch[id]));            cnt[id] = 0;            ch[rt][s[i]-'a'] = id++;        }        rt = ch[rt][s[i]-'a'];        cnt[rt]++;    }}int match(char *s){    int rt = 0;    int len = strlen(s);    for(int i = 0; i < len; i++)    {        if(!ch[rt][s[i]-'a'])            return 0;        rt = ch[rt][s[i]-'a'];    }    return cnt[rt];}int main(){    id = 1;    memset(ch[0], 0, sizeof(ch[0]));    while(gets(str))    {        if(!strlen(str)) break;        Insert(str);    }    while(gets(str) != NULL)        printf("%d\n", match(str));    return 0;}

链表模板(记得及时清空):

#include<iostream>  #include<cstdio>  #include<cstring>  #include<algorithm>  using namespace std;  const int maxn = 105;  char str[maxn];  struct node  {      int cnt;//根据需要变化,这里是记录有该前缀的数量      struct node *next[26];      //next是表示每层有多少种类的数,如果只是小写字母,则26即可,      //若改为大小写字母,则是52,若再加上数字,则是62了      node()      {          cnt = 0;          memset(next, 0, sizeof(next));      }  };    node *root = NULL;    void buildTrie(char *s)  {      node *p = root;      node *tmp = NULL;      int len = strlen(s);      for(int i = 0; i < len; i++)      {          if(p->next[s[i]-'a'] == NULL)   //该前缀没出现过          {              tmp = new node;              p->next[s[i]-'a'] = tmp;          }          p = p->next[s[i]-'a'];          p->cnt++;      }  }    int findTrie(char *s)  {      node *p = root;      int len = strlen(s);      for(int i = 0; i < len; i++)      {          if(p->next[s[i]-'a'] == NULL)   //不存在以该字符串为前缀              return 0;          p = p->next[s[i]-'a'];      }      return p->cnt;  }    void deleateTrie(node *cur)//动态字典树,有时会超内存, 这时就要记得释放空间了  {      for(int i = 0; i < 26; i++)          if(cur->next[i])              deleateTrie(cur->next[i]);      delete cur;  }    int main(void)  {      root = new node;      while(gets(str))      {          if(!strlen(str)) break;          buildTrie(str);      }      while(gets(str) != NULL)          printf("%d\n", findTrie(str));      return 0;  }  



原创粉丝点击