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;
}


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