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");

}

原文地址:https://www.cnblogs.com/zxj015/p/2740274.html