hdu 1251 统计难题 trie入门

统计难题

Problem Description
Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).
 
Input
输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.

注意:本题只有一组测试数据,处理到文件结束.
 
Output
对于每个提问,给出以该字符串为前缀的单词的数量.
 
Sample Input
banana band bee absolute acm ba b band abc
 
Sample Output
2 3 1 0
 
坑点:题目没有给定输入的字符串个数,我将maxnode = 10000*10 + 10;即认为输入字符串个数不超过10000得到的竟然是TLE...之后把maxnode改成4000*1000 + 10才A;
当字符集较大时,不宜使用26叉trie树,这里使用了左孩子右兄弟建树;
 
#include<cstring>
#include<vector>
#include<cstdio>
using namespace std;

const int maxnode = 4000 * 1000 + 10;//字符串个数乘以长度
const int sigma_size = 26;

// 字母表为全体小写字母的Trie
struct Trie {
  int head[maxnode]; // head[i]为第i个结点的左儿子编号
  int next[maxnode]; // next[i]为第i个结点的右兄弟编号
  char ch[maxnode];  // ch[i]为第i个结点上的字符
  int tot[maxnode];  // tot[i]为第i个结点为根的子树包含的叶结点总数,即该点作为多少个单词的前缀;
  int sz; // 结点总数
  long long ans; // 答案
  void clear() { sz = 1; tot[0] = head[0] = next[0] = 0; } // 初始时只有一个根结点

  // 插入字符串s(包括最后的'\0'),沿途更新tot
  void insert(const char *s) {
    int u = 0, v, n = strlen(s);
    tot[0]++;
    for(int i = 0; i <= n; i++) {// =n是为了加上'\0';
      // 找字符a[i]
      bool found = false;
      for(v = head[u]; v != 0; v = next[v])
        if(ch[v] == s[i]) { // 找到了
          found = true;
          break;
        }
      if(!found) {
        v = sz++; // 新建结点
        tot[v] = 0;
        ch[v] = s[i];
        next[v] = head[u];//将左孩子转为右兄弟
        head[u] = v; // 插入到链表的首部
        head[v] = 0;
      }
      u = v;
      tot[u]++;
    }
  }

  int count(const char *s){
        int v = head[0], n = strlen(s),ans = 0;
        for(int i = 0;i < n; i++){
            while(v != 0 && ch[v] != s[i]) v = next[v];
            if(v == 0) return 0;
            ans = tot[v];
            v = head[v];
        }
        return ans;
    }
}trie;
int main()
{
    trie.clear();
    char s[22];
    while(gets(s),s[0] != '\0')
        trie.insert(s);
    while(scanf("%s",s) == 1 && s[0] != '\0'){
        printf("%d\n",trie.count(s));
    }
    return 0;
}
View Code

 

 
posted @ 2016-03-03 21:27  hxer  阅读(176)  评论(0编辑  收藏  举报