zoukankan      html  css  js  c++  java
  • hdu 1671 Phone List

    题目:

            链接:点击打开链接

    题意:

            给出几组数,推断是否有某组数是还有一组数的前缀。

    算法:

            来源:点击打开链接

            字典树:又称单词查找树Trie树,是一种树形结构。是一种哈希树的变种。典型应用是用于统计。排序和保存大量的字符串(但不仅限于字符串),所以常常被搜索引擎系统用于文本词频统计。

    它的长处是:利用字符串的公共前缀来节约存储空间,最大限度地降低无谓的字符串比較,查询效率比哈希表高。字典树与字典非常相似,当你要查一个单词是不是在字典树中,首先看单词的第一个字母是不是在字典的第一层,假设不在,说明字典树里没有该单词,假设在就在该字母的孩子节点里找是不是有单词的第二个字母,没有说明没有该单词,有的话用相同的方法继续查找.字典树不仅能够用来储存字母,也能够储存数字等其他数据。

    ------------------------------------------------------------

    #define MAXN 26
    struct Trie{
        int v;//字典树到此有多少种心同样的前缀数目,即孩子的结点数
        Trie *next[MAXN];//每层有多少种类的字符
    };
    
    Trie *root;


    生成字典树:

    void creatTrie(char *str)
    {
        int len = strlen(str);
        Trie *p = root,*q;
        for(int i=0; i<len; i++)
        {
            int id = str[i] - 'a';
            if(p->next[id] == NULL)
            {
                q = (Trie*) malloc (sizeof(Trie));
                q->v = 1;
                for(int j=0; j<MAXN; j++)
                    q->next[j] = NULL;
                p->next[id] = q;
                p = p->next[id];
            }
            else
            {
                p->next[id]->v++;
                p = p->next[id];
            }
        }
        p->v = -1;//在结尾处把v改成-1
    }


    字典树的查找:

          (1) 每次从根结点開始一次搜索。
          (2) 取得要查找关键词的第一个字母。并依据该字母选择相应的子树并转到该子树继续进行检索;   (3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择相应的子树进行检索。   
          (4) 迭代过程……   
          (5) 在某个结点处,关键词的全部字母已被取出,则读取附在该结点上的信息。即完毕查找。

    int findTrie(char *str)
    {
        int len = strlen(str);
        Tire *p = root;
        for(int i=0; i<len; i++)
        {
            int id = str[i] - 'a';
            p = p->next[id];
            if(p == NULL)//为空则不存在该前缀的串
                return 0;
            if(p->v == -1)//存在串是此串的前缀
                return -1;
        }
        return -1;//是某串的前缀
    }

    空间释放:

    int dealTrie(Trie *T)
    {
        if(T == NULL)
            return 0;
        for(int i=0; i<MAXN; i++)
        {
            if(T->next[i] != NULL)
                deal(T->next[i]);
        }
        free(T);
        return 0;
    }


    思路:

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    
    typedef struct Trie{
        int v;
        Trie *next[10];
    }Trie;
    
    Trie *root;
    
    void creatTrie(char *str)
    {
        int len = strlen(str);
        Trie *p = root,*q;
        for(int i=0; i<len; i++)
        {
            int id= str[i] - '0';
            if(p->next[id] == NULL)
            {
                q = (Trie*)malloc(sizeof(Trie));
                q->v = 1;
                for(int j=0; j<10; j++)
                    q->next[j] = NULL;
                p->next[id] = q;
                p = p->next[id];
            }
            else
            {
                p->next[id]->v++;
                p = p->next[id];
            }
        }
        p->v = -1;
    }
    
    int findTrie(char *str)
    {
        int len = strlen(str);
        Trie *p = root;
        for(int i=0; i<len; i++)
        {
            int id = str[i] - '0';
            p = p->next[id];
            if(p == NULL)
                return 0;
            if(p->v == -1)
                return -1;
        }
        return -1;
    }
    
    int dealTrie(Trie *T)
    {
        if(T == NULL)
            return 0;
        for(int i=0; i<10; i++)
        {
            if(T->next[i] != NULL)
                dealTrie(T->next[i]);
        }
        free(T);
        return 0;
    }
    
    int main()
    {
        //freopen("input.txt","r",stdin);
        int t,n;
        int flag;
        char str[15];
        scanf("%d",&t);
        while(t--)
        {
            flag = 0;
            root = (Trie *) malloc (sizeof(Trie));
            for(int i=0; i<10; i++)
                root->next[i] = NULL;
            scanf("%d",&n);
            getchar();
            for(int i=0; i<n; i++)
            {
                gets(str);
                if(findTrie(str) == -1)
                    flag = 1;
                if(flag)//已经是前缀了。应继续输入
                    continue;
                creatTrie(str);
            }
            if(flag)
                printf("NO
    ");
            else
                printf("YES
    ");
            dealTrie(root);//会爆内存啊
        }
        return 0;
    }
    

  • 相关阅读:
    【Java TCP/IP Socket】应用程序协议中消息的成帧与解析(含代码)
    【Java TCP/IP Socket】UDP Socket(含代码)
    【Java TCP/IP Socket】TCP Socket(含代码)
    Java NIO —— Buffer(缓冲区)
    java.nio.ByteBuffer 以及flip,clear及rewind区别
    Java文件IO操作应该抛弃File拥抱Paths和Files
    Java网络编程之InetAddress和URL
    Java enum的用法详解
    PAT Basic 1083 是否存在相等的差 (20 分)
    PAT Basic 1082 射击比赛 (20 分)
  • 原文地址:https://www.cnblogs.com/llguanli/p/7260341.html
Copyright © 2011-2022 走看看