trie树,儿子兄弟表示法+uva11732

题意:给出n个字符串,进行两两比较,计算比较的次数。

刚开始用指针写,发现这样写保存信息的时候不好计算,于是学习刘汝佳的儿子兄弟表示,这样建树统计分差点的比较次数是非常方便。

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int maxn=4000*1000*10;
int n;
struct trie
{
    int head[maxn];//第一个孩子节点编号
    int next[maxn];//兄弟编号
    int tot[maxn];//经过这个节点的字符串数量
    char ch[maxn];
    int sz;
    long long ans;
    void clear(){sz=1;ans=0;head[0]=next[0]=tot[0]=0;}
    void insert(char * a)
    {
        int u=0,v,len=strlen(a);
        tot[0]++;
        for(int i=0;i<=len;i++)
        {
            bool found=false;
            for(v=head[u];v!=0;v=next[v])
            {
                if(ch[v]==a[i])
                {
                    found=true;
                    break;
                }
            }
            if(!found)//找不到,新建节点
            {
                v=sz++;
                tot[v]=0;
                next[v]=head[u];
                head[u]=v;
                ch[v]=a[i];
                head[v]=0;
            }
            u=v;
            tot[u]++;
        }
    }
    void dfs(int depth,int u)
    {
        if(head[u]==0)
        {
            ans+=tot[u]*(tot[u]-1)*depth;
            return;
        }
        int sum=0;
        for(int v=head[u];v!=0;v=next[v])
            sum+=tot[v]*(tot[u]-tot[v]);
        ans+=sum/2*(depth*2+1);
        for(int v=head[u];v!=0;v=next[v])
        dfs(depth+1,v);
    }
    long long count()
    {
        ans=0;
        dfs(0,0);
        return ans;
    }
}tree;
int  main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif

    int t=1;
    while(scanf("%d",&n)!=EOF,n)
    {
        char a[4010];
        tree.clear();
        for(int i=0;i<n;i++)
        {
            scanf("%s",a);
            tree.insert(a);
        }
        printf("Case %d: %lld\n",t++,tree.count());
    }
    return 0;
}
    原文作者:Trie树
    原文地址: https://blog.csdn.net/u010660276/article/details/19771751
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞