poj 2001 Trie树 模板题

来源:互联网 发布:vb墨镜价格 编辑:程序博客网 时间:2024/05/02 02:29

Trie树,也叫字典树,可以很方便的储存很多个字符串。以小写英文单词为例,Trie树就是一颗26叉树,每一个节点保存一个英文字母。根节点什么也不保存,从根节点开始,第一层就代表单词的第一个字母,向下直到没有字母为止,就是一个单词。


poj2001   题意是给你最多1000个字符串,要你对于每一个字符串,输出它的最短的一个前缀,通过这个前缀能切仅能在1000个字符串中检索到它自己。


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 50000;
const int size = 26;


int ac[maxn][size];       //存放所有节点的大数组,把所有节点存在一个数组里,有点像链式向前星。存放的值是先一个节点在这个大数组中的位置。
int num[maxn];        //有多少个单词用到了当前节点。
int top;       //类比链式向前星里面的top,表示当前用过了多少节点。
int idx(char c) {return c-'a';}   
void clear(){
    memset(ac[0],0,sizeof(ac[0]));
    top=1;
} //清空,只要把根节点清零就好了。
int New(){
    memset(ac[top],0,sizeof(ac[top]));
    num[top]=0;
    return top++;
}  //如果要用到一个新的节点用这个函数,返回值是新节点在ac数组中的位置。
void insert(char *s){
    int k=0,L=strlen(s);
    for(int i=0;i<L;++i){
        int c=idx(s[i]);
        if(!ac[k][c]){
            ac[k][c]=New();
        }  //如果当前位置没有走到过,就在ac数组中腾一个位置给它。
        k=ac[k][c];  //走向下一个节点。
        num[k]++;  //又有一个单词经过了当前节点。
    }
} //插入一个新的单词。
void find(char *s){
    int k=0,L=strlen(s);
    for(int i=0;i<L;++i){
        printf("%c",s[i]);
        int c=idx(s[i]);
        k=ac[k][c];
        if(num[k]==1){
            printf("\n");
            return ;
        }       
    }
    printf("\n");
}   //根据题意可以调整find函数,总体用法和insert函数差不多。。
char s[1005][100];
int main()
{
//    freopen("data.in","r",stdin);
    clear();
    int k=0;
    while(scanf("%s",s[k])!=EOF){
        insert(s[k++]);
    }
    for(int i=0;i<k;++i){
        printf("%s ",s[i]);
        find(s[i]);
    }
    return 0;
}

0 0