UVA11732 字典树

来源:互联网 发布:微信假红包软件生成器 编辑:程序博客网 时间:2024/06/05 11:33



刘汝佳的训练指南上的题目,见识了左儿子右兄弟的存储方式。

代码如下:

#include <cstdio>#include <cstring>#include <cstring>using namespace std;const int maxn = 4000*1000 + 10;const int sigma_size = 26;const int maxL = 1000+10;int n;int head[maxn]; //第i个节点左儿子编号int Next[maxn]; //第i个节点右兄弟编号char ch[maxn]; //第i个节点的字符int tot[maxn]; //第i个节点为根的子树包含的叶子节点总数int sz; //节点总数long long ans ; //答案char word[maxn];inline void Clear(){    sz = 1;    tot[0] = head[0] = Next[0] = 0;    //初始只有根节点}void Insert(const char *s){    int u = 0, len = strlen(s), v;    bool found;    tot[0]++;    for (int i=0; i<=len; i++) {        found = 0;        for (v = head[u]; v!=0; v = Next[v]){            if (ch[v]==s[i]) {                found = 1;                break;            }        }        if (!found){            v = sz++;            tot[v] = 0;            ch[v] = s[i];            Next[v] = head[u];            head[u] = v;            head[v] = 0;        }        u = v;        tot[u]++;    }}void init(){    Clear();    for (int i=1; i<=n; i++) {        scanf("%s",word);        Insert(word);    }    ans = 0;}void dfs(int depth, int u){    if (head[u]==0) {        ans += tot[u]*(tot[u]-1)*depth;    }    else {        int sum = 0;        for (int v = head[u]; v!=0; v = Next[v]) sum += tot[v]*(tot[u]-tot[v]);        ans += sum/2*(2*depth+1);        for (int v = head[u]; v!=0; v = Next[v]) dfs(depth+1,v);    }}int kase = 0;int main(){    while (scanf("%d",&n) && n){        init();        dfs(0,0);        printf("Case %d: %lld\n",++kase,ans);    }    return 0;}


原创粉丝点击