菜鸟系列——字典树

来源:互联网 发布:淘宝买了假货怎么索赔 编辑:程序博客网 时间:2024/06/06 15:01

做回菜鸟,老老实实重新学起:

字典树


动态模版:

//动态链表实现#define MAXN 26struct node{    node *next[MAXN];    int v;   //根据需要变化};node *root;//字典树建立void createTrie(char *str){    int len = strlen(str);    node *p = root;    for(int i=0; i<len; ++i)    {        int id = str[i]-'a';        if(p->next[id] == NULL)        {            p->next[id] = new node();            p->next[id]->v = 1; //初始v==1            for(int j=0; j<MAXN; ++j)                p->next[id]->next[j] = NULL;            p = p->next[id];        }        else        {            p->next[id]->v++;            p = p->next[id];        }    }}//查找int findTrie(char *str){    int len = strlen(str);    node *p = root;    for(int i=0; i<len; ++i)    {        int id = str[i]-'a';        p = p->next[id];        if(p == NULL)   //若为空集,表示不存以此为前缀的串            return 0;    }    return p->v;//返回以此为前缀的串的数量}//释放空间int dealTrie(node* T){    int i;    if(T==NULL)        return 0;    for(i=0;i<MAXN;i++)    {        if(T->next[i]!=NULL)            dealTrie(T->next[i]);    }    free(T);    return 0;}void solve(int n,int m){    int i,j;    char s[101];    root = new node();    root->v = 1;    for(j=0; j<MAXN; ++j)        root->next[j] = NULL;    for(i=0;i<n;i++)    {        scanf("%s",s);        createTrie(s);    }    for(j=0;j<m;j++)    {        scanf("%s",s);        printf("%d\n",findTrie(s));    }}


静态模版:

//静态数组实现int sum=0,res=0;struct node{    int x,y;    int r;    int next[26];    void init()    {        r=0;        memset(next,-1,sizeof(next));    }}tree[1000005];void insert_tree(char *str){    int i, j, t;    i = j = t = 0;    while(str[i])    {        t = str[i]-'a';        if(tree[j].next[t] == -1)        {            tree[sum].init();            tree[j].next[t] = sum++;        }        j = tree[j].next[t];        tree[j].r++;//记录以此为前缀的单词的数量        i++;    }}void query_tree(char *str){    int i,j,t;    i = j = t = 0;    while(str[i])    {        t = str[i]-'a';        if(tree[j].next[t] == -1)        {            res=0;            return;        }        j=tree[j].next[t];        i++;    }    res=tree[j].r;//以此为前缀的单词的数量}


eg:

POJ2001 Shortest Prefixes

http://poj.org/problem?id=2001

题意:

求给出字典中每个单词能够被特别的分别出最短前缀;

思路:

字典树模版,遇到小于2的节点停止即可;

code:

#define N 123456s#define MAXN 26char s[N][30];struct node{    node *next[MAXN];    int v;   //根据需要变化};node *root;//字典树建立void createTrie(char *str){    int len = strlen(str);    node *p = root;    for(int i=0; i<len; ++i)    {        int id = str[i]-'a';        if(p->next[id] == NULL)        {            p->next[id] = new node();            p->next[id]->v = 1; //初始v==1            for(int j=0; j<MAXN; ++j)                p->next[id]->next[j] = NULL;            p = p->next[id];        }        else        {            p->next[id]->v++;            p = p->next[id];        }    }}//查找int findTrie(char *str){    int len = strlen(str);    node *p = root;    for(int i=0; i<len; ++i)    {        int id = str[i]-'a';        p = p->next[id];        if(p == NULL)   //若为空集,表示不存以此为前缀的串            return 0;        printf("%c",str[i]);        if(p->v < 2)            return 0;    }    return p->v;//返回以此为前缀的串的数量}//释放空间int dealTrie(node* T){    int i;    if(T==NULL)        return 0;    for(i=0;i<MAXN;i++)    {        if(T->next[i]!=NULL)            dealTrie(T->next[i]);    }    free(T);    return 0;}void solve(){    int i,j;    root = new node();    root->v = 1;    for(j=0; j<MAXN; ++j)        root->next[j] = NULL;    i=0;    while(scanf("%s",s[i])!=EOF)    {        createTrie(s[i]);        i++;    }    for(j=0;j<i;j++)    {        printf("%s ",s[j]);        findTrie(s[j]);        printf("\n");    }}int main(){    int i,j,k,kk,t,x,y;    #ifndef ONLINE_JUDGE        freopen("test.txt","r",stdin);    #endif    solve();    return 0;}

0 0