poj 2001 Shortest Prefixes (trie)


拿到这题,大致的画了画图,发现只要标记好每个节点出现的次数就好了。 

插入时,若字符存在,n++,若不存在建立新节点,他本身也为自己的前缀。

查找时,若next[k]->nCount!=1,说明其子节点有多个,无法确定唯一,则输出该字符,若nCount=1,则可以结束查找了。

code:

#include<cstdio>
#include<cstring>

char str[ 1001][ 21] ;
#define MAX 30  // 字符集大小
typedef  struct TrieNode{
     int nCount ;  // 记录该字符出现次数
     struct TrieNode *next[MAX] ;
}TrieNode ;

TrieNode Memory[ 1000000] ;
int allocp =  0 ;

/* 初始化 */
void InitTrieRoot(TrieNode **pRoot){
    *pRoot = NULL ;
}

/* 创建新结点 */
TrieNode *CreateTrieNode(){
     int i ;
    TrieNode *p ;
    p = &Memory[allocp++] ;
    p->nCount =  1 ;
     for(i= 0; i<MAX; i++){
        p->next[i] = NULL ;
    }
     return p ;
}

/* 插入 */
void InsertTrie(TrieNode **pRoot,  char *s){
     int i, k ;
    TrieNode *p ;
     if(!(p=*pRoot)){
        p = *pRoot = CreateTrieNode() ;
    }
    i =  0 ;
     while(s[i]){
        k = s[i++] -  ' a ' ;  // 确定branch
         if(p->next[k])
            p->next[k]->nCount ++ ;
         else
            p->next[k] = CreateTrieNode() ;
        p = p->next[k] ;
    }
}

// 查找
void SearchTrie(TrieNode **pRoot,  char *s){
    TrieNode *p ;
    p = *pRoot ;
     int i , k ;
    i =  0 ;
     while(s[i]){
        k = s[i++] -  ' a ' ;
         if(p->next[k]==NULL||p->next[k]->nCount== 1){
            printf( " %c ", k+ ' a ') ;
             break ;
        }
         else{
            p = p->next[k] ;
            printf( " %c ", k+ ' a ') ;
        }
    }
    printf( " \n ") ;
}
int main(){
     int n =  0, i ;
    allocp =  0 ;

    TrieNode *root = NULL ;
    InitTrieRoot(&root) ;

     while(gets(str[n])&&str[n][ 0])
        InsertTrie(&root, str[n++]) ;
     for(i= 0; i<n; i++){
        printf( " %s  ", str[i]) ;
        SearchTrie(&root, str[i]) ;
    }
     return  0 ;

你可能感兴趣的:(test)