zoukankan      html  css  js  c++  java
  • 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
    ", Case++, mmin);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    2.java基础语法(上)
    1.java概述
    Qt layout透明的问题
    Duilib 关于ChildLayout崩溃的问题
    关于注册表使用的几个问题
    win32接口获取ping值
    Web开发中遇到的问题
    DuiLib 窗口透明方法
    通过进程名杀死进程的方法--WIN32
    关于在Qt的MainWindow窗口中添加Layout的问题
  • 原文地址:https://www.cnblogs.com/chenyang920/p/4786256.html
Copyright © 2011-2022 走看看