zoukankan      html  css  js  c++  java
  • Tire树

     

    Trie树就是字符树,其核心思想就是空间换时间。

    举个简单的例子。

    给你100000个长度不超过10的单词。对于每一个单词,我们要判断他出没出现过,如果出现了,第一次出现第几个位置。

    这题当然可以用hash来,但是我要介绍的是trie树。在某些方面它的用途更大。比如说对于某一个单词,我要询问它的前缀是否出现过。这样hash就不好搞了,而用trie还是很简单。

    现在回到例子中,如果我们用最傻的方法,对于每一个单词,我们都要去查找它前面的单词中是否有它。那么这个算法的复杂度就是O(n^2)。显然对于100000的范围难以接受。现在我们换个思路想。假设我要查询的单词是abcd,那么在他前面的单词中,以bcdf之类开头的我显然不必考虑。而只要找以a开头的中是否存在abcd就可以了。同样的,在以a开头中的单词中,我们只要考虑以b为第二个字母的……这样一个树的模型就渐渐清晰了……

    假设有babcabdbcdabcdefghii6个单词,我们构建的树就是这样的。

    Tire树 - 某年某月 - zxj015的博客

    对于每一个节点,从根遍历到他的过程就是一个单词,如果这个节点被标记为红色,就表示这个单词存在,否则不存在。

    那么,对于一个单词,我只要顺着他从跟走到对应的节点,再看这个节点是否被标记为红色就可以知道它是否出现过了。把这个节点标记为红色,就相当于插入了这个单词。

    这样一来我们询问和插入可以一起完成,所用时间仅仅为单词长度,在这一个样例,便是10

    我们可以看到,trie树每一层的节点数是26^i级别的。所以为了节省空间。我们用动态链表,或者用数组来模拟动态。空间的花费,不会超过单词数×单词长度。

    看个例子把,也是转载的,继续学习!

     http://acm.szu.edu.cn/wiki/index.php/Problem:H67:ACgirl%27s_SMS_guards

    //trie树部分:给一组手机号,查找某一手机号是否在这一组手机号。

    #include<iostream>

    #include<stdio.h>

    #include<stdlib.h>

    //#include<string.h>

    using namespace std;

     

    node data[1100100];

    int pointer = 0;

    node * root;

    typedef struct node

    {

           struct node * pNext[10];

           bool isEnd;

           node()

           {

                  isEnd = false;

           }

    }node;

    node * getNode()

    {

           return &data[pointer++];

    }

    void insert(node * root, char * strTel)

    {

           node * pCur = root;

           int pos = 0;

           while (*strTel)

           {

                  pos = *strTel - '0';

                  if (NULL == pCur->pNext[pos])

                  {

                         pCur->pNext[pos] = getNode();

                  }

                  pCur = pCur->pNext[pos];

                  ++strTel;

           }

           pCur->isEnd = true;

    }

     

    //查询手机号是否为黑名单

    bool query(node * root, char * strTel)

    {

           node * pCur = root;

           int pos = 0;

          

           while (*strTel)

           {

                  if (!(*strTel >= '0' && *strTel <= '9'))

                  {

                         return false;

                  }

                  pos = *strTel - '0';

                  if (NULL == pCur->pNext[pos])

                  {

                         return false;

                  }

                  pCur = pCur->pNext[pos];

                  ++strTel;

           }

           if (!pCur->isEnd)

           {

                  return false;

           }

           return true;

    }

     

     

     

    int main()

    {

          long year,month,day,hour,minute,second,k,m,i,j,ans,n,Case=1,flag,num;

          char p[14],q[130],tel[130],con[130];

          scanf("%ld",&n);

          while(n--)

          {

            ans=0;

             root = getNode();

            printf("Case %ld:\n",Case++);

            scanf("%ld",&m);

            getchar();

            for(i=0;i<m;i++)

            {

              gets(p);

              insert(root,p);

            }

            scanf("%ld",&k);

            getchar();

            for(i=0;i<k;i++)

            {

              gets(q);

              num=sscanf(q,"%ld-%ld-%ld:%ld:%ld:%ld,%[0-9],%[^'/0']",&year,&month,&day,&hour,&minute,&second,tel,con);

              if(num!=8)

                continue;

              if(month>12||month<1)

                continue;

              if(day<1)

                continue;

              if((year%4==0&&year%100!=4)||year%400==0)

              {

                if(month==2&&day>29)

                   continue;

              }

              else

              {

                 if(month==2&&day>28)

                   continue;

               }

               if(month==1||month==3||month==5||month==7||month==8||month==10||month==12)

               {

                  if(day>31)

                    continue;

               }

                else

                {

                    if(day>30)

                      continue;

                }

                if(hour>23||hour<0||minute>59||minute<0||second>59||second<0)

                    continue;

                if(strlen(tel)>11)

                {

                  continue;

                }

                if(strlen(con)>100)

                   continue;

                if(!query( root,tel))

                   continue;

                j=0;

                while(q[j]!=',')

                {

                       printf("%c",q[j]);

                       j++;

                }

                printf(",15980698888,Sorry,I am ACb0y's girl friend\n");

                ans++;

              }

              printf("count = %ld\n",ans);

            }

           system("pause");

    }

  • 相关阅读:
    实时需要分析
    .NET 单元测试的艺术&单元测试之道C#版
    代码演示C#各2.0到8.0版本[FK,2.0-4.8.0]
    微软Visual Studio Code 0.8.0发布,新增多种主题
    ASP.NET 5 Beta 7 版本
    软件开发设计原则
    Immutable(不可变)集合
    使用Hystrix提高系统可用性
    微软发布 Windows Server 2016 预览版第三版,开发者要重点关注Nano Server
    Akka.NET v1.0 已发布,支持Mono
  • 原文地址:https://www.cnblogs.com/zxj015/p/2740274.html
Copyright © 2011-2022 走看看