HUST-1350 Trie

1350 - Trie

时间限制:1秒 内存限制:128兆

104 次提交 35 次通过
题目描述
In computer science, a trie, is an ordered tree data structure that is used to store an associative array where the keys are usually strings. Each position in the tree shows what key it is associated with and All the descendants of a node have a common prefix of the string associated with that node, have and only have one more character than its father node. the root of the trie is associated with the empty string. For example, if we put 6 words of “to”, “tea”, “ted”, “ten”, “a”, “inn” to a trie, it will be the form of figure.  In the computer science, a trie is a tree. For a tree, we define the leave node is the node without any descendants and only have an edge connect in. So in this example, the leave node is “to”, “tea”, “ted”, “ten”, “a” and “inn”. And we define the distance between two node is the minimum edge from a node to another node must pass. So the distance between “a” and “te” is 3, “to” and “inn” is 5. Finally, we define the value of a node is the sum of the node to the entire leave node’s distance. And the value of a tree is equal the value of a node which have the minimum value. Now give you a list of words. Put them into a trie, and calculate the value of this trie.
输入
The first line is T, indicate there are T cases. For each case, the first line is N, indicate there are N words. Next N lines, each line have a word only include the lower case letters and no two words are the same. (N<=50 and the length of a word less than 10)
输出
For each case output a line with the value of the trie.
样例输入
2
6
a
to
tea
ted
ten
inn
4
sa
sb
sc
sd
样例输出
Case #1: 13
Case #2: 5



/////////////////////////////////////
For the second case, if the root has only one child, it’s a special leaf and must be calculate.
提示
来源
Hong Zehua, HUST Campus 2009

 

/**
    题意:给几个字符串,构成一个字典树,求哪个节点到每个叶子的距离最短的,最短是多少
    做法:先建立一个字典树,然后求公共祖先(求得是所有点到叶子节点的最短的距离)
**/
#include <iostream>
#include <algorithm>
#include <cmath>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;
#define maxn 100010
int tot = 0 ;
const int MAXN = 100010;
const int DEG = 30;
int num[maxn];
int tot2 = 0;
int tot3 = 0;
int num1[maxn];
int indegree[maxn];
int mmap[maxn];
int mm = 0;
struct Node
{
    int x;
    int y;
    int flag;
    Node() {};
    Node(int _x, int _y) {
        x = _x;
        y = _y;
        flag = 0;
    }
} node[maxn << 1];
struct Trie
{
    int next[maxn][30], end[maxn];
    int root;
    int L;
    int newnode() {
        for(int i = 0; i < 26; i++) {
            next[L][i] = -1;
        }
        end[L++] = 0;
        return L - 1;
    }
    void init() {
        L = 0;
        root = newnode();
    }
    void insert(char buf[]) {
        int len = strlen(buf);
        int now = root;
        for(int i = 0; i < len; i++) {
            if(next[now][buf[i] - 'a'] == -1) {
                next[now][buf[i] - 'a'] = newnode();
                node[tot].y = next[now][buf[i] - 'a'] + 1;
                node[tot].x = now + 1;
                node[tot].flag = 0;
                tot++;
            }
            now = next[now][buf[i] - 'a'];
        }
        node[tot - 1].flag = 1;
        num[tot2++] = node[tot - 1].y;
        end[now]++;
    }
};
Trie ac;
struct Edge
{
    int to;
    int next;
} edge[MAXN * 2];
int head[MAXN], tot1;
void addedge(int u, int v)
{
    edge[tot1].to = v;
    edge[tot1].next = head[u];
    head[u] = tot1++;
}
void init()
{
    tot1 = 0;
    memset(head, -1, sizeof(head));
}
int fa[MAXN << 1][DEG];
int deg[MAXN << 1];
void bfs(int root)
{
    queue<int>que;
    deg[root] = 0;
    fa[root][0] = root;
    que.push(root);
    while(!que.empty())
    {
        int tmp = que.front();
        que.pop();
        for(int i = 1; i < DEG; i++) {
            fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1];
        }
        for(int i = head[tmp]; i != -1; i = edge[i].next)
        {   int v = edge[i].to;
            if(v == fa[tmp][0]) {
                continue;
            }
            deg[v] = deg[tmp] + 1;
            fa[v][0] = tmp;
            que.push(v);
        }
    }
}
int LCA(int u, int v)
{
    if(deg[u] > deg[v]) {
        swap(u, v);
    }
    int hu = deg[u], hv = deg[v];
    int tu = u, tv = v;
    for(int det = hv - hu, i = 0; det; det >>= 1, i++)
        if(det & 1) {
            tv = fa[tv][i];
        }
    if(tu == tv) {
        return tu;
    }
    for(int i = DEG - 1; i >= 0; i--)
    {
        if(fa[tu][i] == fa[tv][i]) {
            continue;
        }
        tu = fa[tu][i];
        tv = fa[tv][i];
    }
    return fa[tu][0];
}
bool flag[MAXN];
char buf[30];
int main()
{
    //freopen("in.txt", "r", stdin);
    int Case = 1;
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int n;
        tot = 1;    ///边的数目
        tot2 = 0;   ///叶子节点的数目  如果根节点存在Case 2 中的情况也加进去
        tot3 = 0;   ///不是叶子的节点的节点
        mm = 0;
        memset(node, 0, sizeof(node));
        memset(indegree, 0, sizeof(indegree));
        memset(flag, 0, sizeof(flag));
        scanf("%d", &n);
        ac.init();
        for(int i = 0; i < n; i++)
        {
            scanf("%s", buf);
            ac.insert(buf);
        }
        init();
        int yy = 0;
        for(int i = 1; i < tot; i++)
        {
            addedge(node[i].x, node[i].y);
            addedge(node[i].y, node[i].x);
            indegree[node[i].x] ++;
            indegree[node[i].y] ++;
            yy = max(yy, max(node[i].x, node[i].y));
        }
        for(int i = 1; i < tot; i++) {
            if(indegree[node[i].x] == 1) {
                mmap[mm++] = node[i].x;
            }
            else {
                num1[tot3++] = node[i].x;
            }
            if(indegree[node[i].y] == 1) {
                mmap[mm++] = node[i].y;
            }
            else {
                num1[tot3++] = node[i].y;
            }
        }
        sort(mmap, mmap + mm);
        sort(num1, num1 + tot3);
        int newmm = unique(mmap, mmap + mm) - mmap;
        int newtot3 = unique(num1, num1 + tot3) - num1;
        bfs(1);
        int mmin = 0xfffffff;
        for(int i = 1; i <= yy; i++)
        {
            int temp = 0;
            for(int j = 0; j < newmm; j++)
            {
                if(i != mmap[j]) {
                    int tt = LCA(i, mmap[j]);
                    int res = 0;
                    res = abs(deg[i] - deg[tt]) + abs(deg[mmap[j]] - deg[tt]);
                    temp += res;
                }
            }
            mmin = min(mmin, temp);
        }
        printf("Case #%d: %d\n", Case++, mmin);
    }
    return 0;
}
View Code

 

posted on 2015-09-06 15:49  `Elaine  阅读(243)  评论(0编辑  收藏  举报

导航