UVa 11732 難難難啊

白書上的第二個字典樹,這個題目需要用到字典樹的一種新的寫法,用到了在分支的時候採用的左兒子、右兄弟的寫法,非常的實用的寫法,也是非常的新穎的。這個題難度還是蠻高的,數據要用LL,不然會溢出,因爲字符集比較大啊!

可參考博客:http://www.cnblogs.com/372465774y/archive/2013/04/10/3012071.html

http://blog.csdn.net/mobius_strip/article/details/27260579

#include<cstdio>
#include<cstring>
#include<algorithm>


using namespace std;

const int maxnode=4000010;
const int maxn=1050;
int n;
long long sum;
char ch[maxnode];
int son[maxnode],bro[maxnode];
int val[maxnode]; //每個i爲根的val[i]爲其葉子結點總數目
int sz;
void init()
{
   sum=0;
   sz=1;
  val[0]=son[0]=bro[0]=0;
}
int idx(char c)
{
    return c-'a';
}
void insert(char *s)
{
   int u=0,n=strlen(s);
   val[0]++;
   for(int i=0;i<=n;i++)
   {
      bool f=false;int v;
      for(v=son[u];v!=0;v=bro[v])
      {
          if(ch[v]==s[i])
          {
              f=true;
              break;
          }
      }
        if(!f)
        {
            v=sz++;
            val[v]=0;
            ch[v]=s[i];
            bro[v]=son[u];
            son[u]=v;
            son[v]=0;
        }
        u=v;
        val[u]++;
   }
}

void dfs(int depth,int u)
{
  if(son[u]==0)
        sum+=val[u]*(val[u]-1)*depth;
  else
  {
      int s=0;
      for(int v=son[u];v!=0;v=bro[v])
      {
          s+=val[v]*(val[u]-val[v]);
      }
      sum+=s/2*(2*depth+1);
      for(int v=son[u];v!=0;v=bro[v])
        dfs(depth+1,v);
  }
}

long long counts()
{
   dfs(0,0);
   return sum;
}

int main()
{
    int kase=1;
    char tmp[maxn];
    while(scanf("%d",&n)!=EOF)
    {
     if(n==0)
        break;
        init();
     for(int i=0;i<n;i++)
     {
         scanf("%s",tmp);
         insert(tmp);
     }
       printf("Case %d: %lld\n",kase++,counts());

    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章