Trie树



Trie树_第1张图片

这么多年过去了, 最开始接触的时候是大二,那个时候觉得思想蛮好懂的,就是实现起来困难。

事隔这么多年,一晃4年都快过去了,重新写了一遍,觉得蛮有感触,老狗,加油!

前缀个数

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

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

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

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

Sample Input
   
   
   
   
banana band bee absolute acm ba b band abc
 

Sample Output
   
   
   
   
2 3 1 0
 

const int Max_N = 26 ;

struct TrieNode{
       int EndSize ;
       TrieNode *next[Max_N] ;
};

void insert_string(TrieNode *root , char *s){
     if(root == NULL || *s == '\0')
        return ;
     TrieNode *now = root ;
     while(*s != '\0'){
          if(now->next[*s - 'a'] == NULL){
                TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode)) ;
                for(int i = 0 ; i < Max_N ; i++)
                    node->next[i] = NULL ;
                node->EndSize = 1 ;
                now->next[*s - 'a'] = node ;
                now = node ;
          }
          else{
             now = now->next[*s - 'a'] ;
             now->EndSize++ ;
          }
          s++ ;
     }
}

int  search_string(TrieNode *root , char *s){
     if(root == NULL || *s == '\0')
        return 0 ;
     TrieNode *now = root ;
     while(now != NULL && *s != '\0'){
          now = now->next[*s - 'a'] ;
          s++ ;
     }
     if(now == NULL)
        return 0 ;
     else
        return now->EndSize ;
}

void clear_trie(TrieNode *root){
     for(int i = 0 ; i < Max_N ; i++){
          if(root->next[i] != NULL)
            clear_trie(root->next[i]) ;
     }
     free(root) ;
}

int  main(){
     char str[100] ;
     TrieNode *root = (TrieNode *)malloc(sizeof(TrieNode)) ;
     for(int i = 0 ; i < Max_N ; i++)
        root->next[i] = NULL ;
     while(gets(str)){
           if(*str == '\0')
              break ;
           insert_string(root , str) ;
     }
     while(gets(str)){
          printf("%d\n" ,search_string(root , str)) ;
     }
     clear_trie(root) ;
     return 0 ;
}


                      给N个串,问是否不存在任何2个串,短串不是长串的前缀。

http://acm.hdu.edu.cn/showproblem.php?pid=1671

const  int Max_N = 10 ;

struct TrieNode{
       int isEndstr ;
       TrieNode *next[Max_N] ;
       TrieNode(){
            for(int i = 0 ; i < Max_N ; i++)
                this->next[i] = NULL ;
            isEndstr = 0 ;
       }
};

int  insert_string(TrieNode *root , char *s){
     TrieNode *now = root ;
     while(*(s+1) != '\0'){
          if(now->next[*s - '0'] == NULL){
               TrieNode *node = new TrieNode() ;
               now->next[*s - '0'] = node ;
               now = node ;
          }
          else{
               now = now->next[*s - '0'] ;
               if(now->isEndstr)  //此处有单词结束
                  return 0 ;
          }
          s++ ;
     }
     if(now->next[*s - '0'] == NULL){
               TrieNode *node = new TrieNode() ;
               now->next[*s - '0'] = node ;
               now = node ;
      }
      else  //结束单词之前出现过。
           return 0 ;
     now->isEndstr = 1 ;
     return 1 ;
}

void clear_trie(TrieNode *root){
     for(int i = 0 ; i < Max_N ; i++){
          if(root->next[i] != NULL)
             clear_trie(root->next[i]) ;
     }
     free(root) ;
}

char word[10008][11];
int N ;

int  Ans(TrieNode *root){
     int i ;
     for(i = 1 ; i <= N ; i++){
          if(! insert_string(root , word[i]))
              return  0 ;
     }
     return 1 ;
}

int  main(){
     int T ,i ;
     cin>>T ;
     while(T--){
           scanf("%d" ,&N) ;
           for(i = 1 ; i <= N ; i++)
               scanf("%s" , word[i]) ;
           TrieNode *root = new TrieNode() ;
           if(Ans(root))
              puts("YES") ;
           else
              puts("NO") ;
           clear_trie(root) ;
     }
     return  0 ;
}


统计给点N个字符串,出现次数最多的一个,并输出 。

动物统计加强版

描述
在美丽大兴安岭原始森林中存在数量繁多的物种,在勘察员带来的各种动物资料中有未统计数量的原始动物的名单。科学家想判断这片森林中哪种动物的数量最多,但是由于数据太过庞大,科学家终于忍受不了,想请聪明如你的ACMer来帮忙。
输入
第一行输入动物名字的数量N(1<= N <= 4000000),接下来的N行输入N个字符串表示动物的名字(字符串的长度不超过10,字符串全为小写字母,并且只有一组测试数据)。 
输出
输出这些动物中最多的动物的名字与数量,并用空格隔开(数据保证最多的动物不会出现两种以上)。 
样例输入
10
boar
pig
sheep
gazelle
sheep
sheep
alpaca
alpaca
marmot
mole
样例输出
sheep 3

在节点中加入一个父亲节点指针,这样输出串的时候就可以找到父亲节点。


const int Max_N = 26 ;

struct TrieNode{
       int  EndSize ;
       char ch  ;
       TrieNode *next[Max_N] ;
       TrieNode *father ;
       TrieNode(){}
       TrieNode(char c){
               EndSize = 0 ;
               for(int i = 0 ; i < Max_N ; i++)
                  this->next[i] = NULL ;
               ch = c  ;
       }
};

TrieNode *EndNode ;
int   Max_string ;

void insert_string(TrieNode *root , char *s){
     if(root == NULL || *s == '\0')
        return  ;
     TrieNode *now = root ;
     while(*(s+1) != '\0'){
          if(now->next[*s - 'a'] == NULL){
               TrieNode *node = new TrieNode(*s) ;
               node->father = now ;
               now->next[*s - 'a'] = node ;
               now = node ;
          }
          else
               now = now->next[*s - 'a'] ;
          s++ ;
     }
     if(now->next[*s - 'a'] == NULL){
          TrieNode *node = new TrieNode(*s) ;
          node->father = now ;
          now->next[*s - 'a'] = node ;
          now = node ;
     }
     else
          now = now->next[*s - 'a'] ;
     now->EndSize++ ;
     if(Max_string < now->EndSize){
         EndNode = now  ;
         Max_string = now->EndSize ;
     }
}

void clear_trie(TrieNode *root){
     for(int i = 0 ; i < Max_N ; i++){
          if(root->next[i] != NULL)
              clear_trie(root->next[i]) ;
     }
     free(root) ;
}

void Ans(TrieNode *root){
     vector<int>ans ;
     ans.clear() ;
     TrieNode *now = EndNode ;
     while(now->father != root){
            ans.push_back(now->ch) ;
            now = now->father ;
     }
      ans.push_back(now->ch) ;
      for(int i = ans.size() -1 ; i >= 0 ; i--)
         putchar(ans[i]) ;
    return  ;
}

int  main(){
     int n  ;
     char str[12] ;
     while(scanf("%d" ,&n) != EOF){
           TrieNode *root = new TrieNode('*') ;
           Max_string = 0 ;
           while(n--){
                scanf("%s" ,str)  ;
                insert_string(root , str) ;
           }
           Ans(root) ;
           printf(" %d\n" , Max_string) ;
           clear_trie(root) ;
     }
     return 0 ;
}


Xor Sum
Zeus 和 Prometheus 做了一个游戏,Prometheus 给 Zeus 一个集合,集合中包含了N个正整数,随后 Prometheus 将向 Zeus 发起M次询问,每次询问中包含一个正整数 S ,之后 Zeus 需要在集合当中找出一个正整数 K ,使得 K 与 S 的异或结果最大。Prometheus 为了让 Zeus 看到人类的伟大,随即同意 Zeus 可以向人类求助。你能证明人类的智慧么?
 


Input
输入包含若干组测试数据,每组测试数据包含若干行。
输入的第一行是一个整数T(T < 10),表示共有T组数据。
每组数据的第一行输入两个正整数N,M(<1=N,M<=100000),接下来一行,包含N个正整数,代表 Zeus 的获得的集合,之后M行,每行一个正整数S,代表 Prometheus 询问的正整数。所有正整数均不超过2^32。
 


Output
对于每组数据,首先需要输出单独一行”Case #?:”,其中问号处应填入当前的数据组数,组数从1开始计算。
对于每个询问,输出一个正整数K,使得K与S异或值最大。
 


Sample Input
2
3 2
3 4 5
1
5
4 1
4 6 5 6
3
 


Sample Output
Case #1:
4
3
Case #2:
4
 


Source
2014年百度之星程序设计大赛 - 资格赛

struct  TrieNode{
        int  val ;
        TrieNode *next[2] ;
};

void   Insert(TrieNode * root , int  x){
       int t ;
       TrieNode *now = root ;
       for(int i = 31 ; i >= 0 ; i--){
            if(x & (1<<i)) t = 1 ;
            else           t = 0 ;
            if(now->next[t] == NULL){
                  TrieNode *node = (TrieNode *)malloc(sizeof(TrieNode)) ;
                  node->next[0] = node->next[1] = NULL ;
                  now->next[t] = node ;
                  now = node ;
            }
            else now = now->next[t] ;
       }
       now->val = x ;
}

int   Get(TrieNode *root , int x){
     int t  ;
     TrieNode *now = root ;
     for(int i = 31 ; i >= 0 ; i--){
            if(x & (1<<i)) t = 1 ;
            else           t = 0 ;
            if(now->next[t^1] != NULL)
                now = now->next[t^1] ;
            else now = now->next[t] ;
     }
     return now->val ;
}

void  Clear(TrieNode *root){
      for(int i = 0 ; i <= 1 ; i++){
           if(root->next[i] != NULL)
              Clear(root->next[i]) ;
      }
      free(root) ;
}

int  main(){
     int t , n ,  m  , T = 1  , x ;
     cin>>t  ;
     while(t--){
          TrieNode *root = (TrieNode *)malloc(sizeof(TrieNode)) ;
          root->next[0] = root->next[1] = NULL ;
          scanf("%d%d" ,&n,&m) ;
          while(n--){
               scanf("%d" ,&x) ;
               Insert(root , x) ;
          }
          printf("Case #%d:\n" , T++) ;
          while(m--){
               scanf("%d" ,&x) ;
               printf("%d\n" ,Get(root , x)) ;
          }
     }
     return 0 ;
}




你可能感兴趣的:(Trie树)