UVA 11732 "strcmp()" Anyone(字典树+左儿子-右兄弟表示法)

来源:互联网 发布:3d样板房软件 编辑:程序博客网 时间:2024/05/21 19:25

如果用常规发放存储字典树,那么空间需要2亿多int,肯定会爆空间,所以用左耳子-右兄弟的方法存字典树。

然后当节点是叶子结点的时候那么比较次数就是tot[u]*(tot[u]-1)*dep,如果非叶子结点,那么统计他的儿子节点与兄弟节点的个数然后相乘最后除2再乘比较次数就是到目前节点的比较次数了。

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define rep(i,a,b) for(int i=(a);i<=(b);i++)#define ss(x) scanf("%d",&x)const int maxnode=4000*1000+5;struct Trie{    int head[maxnode];    int next[maxnode];    char ch[maxnode];    int tot[maxnode];    int sz;    long long ans;    void clear() {sz=1;head[0]=next[0]=tot[0]=0;}        void insert(char *s)    {        int n=(int)strlen(s);int u=0,v;        tot[0]++;        rep(i,0,n){            bool find=false;            for(v=head[u];v!=0;v=next[v])                if(ch[v]==s[i]) {find=true;break;}            if(!find)            {                v=sz++;                tot[v]=0;                ch[v]=s[i];                next[v]=head[u];                head[u]=v;                head[v]=0;            }            u=v;            tot[u]++;        }    }        void dfs(int u,int dep)    {        if(head[u]==0) ans+=tot[u]*(tot[u]-1)*dep;        else{            long long sum=0;            for(int v=head[u];v!=0;v=next[v])                sum+=tot[v]*(tot[u]-tot[v]);            ans+=sum/2*(2*dep+1);            for(int v=head[u];v!=0;v=next[v])                dfs(v,dep+1);        }    }        long long count()    {        ans=0;        dfs(0,0);        return ans;    }};Trie trie;char word[1000+5];int main(){    int n,kase=0;    while(true)    {        ss(n);if(n==0) break;        trie.clear();        rep(i,1,n) {scanf("%s",word);trie.insert(word);}        printf("Case %d: %lld\n",++kase,trie.count());    }}


0 0