zoukankan      html  css  js  c++  java
  • uva 11732 (trie树)

    题意:求N个字符串两两比较,共比较了多少次?

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    
    typedef long long LL;
    const int maxnode = 4000 * 1000 + 10;
    
    // 字母表为全体小写字母的Trie
    struct Trie
    {
        int head[maxnode]; // head[i]为第i个结点的左儿子编号
        int next[maxnode]; // next[i]为第i个结点的右兄弟编号
        char ch[maxnode];  // ch[i]为第i个结点上的字符
        int tot[maxnode];  // tot[i]为第i个结点为根的子树包含的叶结点总数
        int sz; // 结点总数
        LL ans; // 答案
        void clear() { sz = 1; tot[0] = head[0] = next[0] = 0; } // 初始时只有一个根结点
        
        // 插入字符串s(包括最后的''),沿途更新tot
        void insert(const char *s)
        {
            int u = 0, v, n = strlen(s);
            tot[0]++;
            for(int i = 0; i <= n; i++) 
            {
                // 找字符a[i]
                bool found = false;
                for(v = head[u]; v != 0; v = next[v])
                if(ch[v] == s[i]) { found = true;break;}
                if(!found) 
                {
                    v = sz++; // 新建结点
                    tot[v] = 0;
                    ch[v] = s[i];
                    next[v] = head[u];//v添加右兄弟节点
                    head[u] = v; // u添加左儿子节点
                    head[v] = 0;
                }
                u = v;
                tot[u]++;
            }
        }
        
        // 统计LCP=u的所有单词两两的比较次数之和 
        void dfs(int depth, int u) 
        {
            int v;
            if(head[u] == 0) // 叶结点
                ans += tot[u] * (tot[u] - 1) * depth;
            else
            {
                int sum = 0;
                for(v = head[u]; v != 0; v = next[v])
                    sum += tot[v] * (tot[u] - tot[v]); // 子树v中选一个串,其他子树中再选一个
                ans += sum / 2 * (2 * depth + 1); // 除以2是每种选法统计了两次
                for(v = head[u]; v != 0; v = next[v])
                    dfs(depth+1, v);
            }
        }
        
        // 统计
        LL count() 
        {
            ans = 0;
            dfs(0, 0);
            return ans;
        }
    };
    
    #include<cstdio>
    const int maxl = 1000 + 10;   // 每个单词最大长度
    
    int n;
    char word[maxl];
    Trie trie;
    
    int main() 
    {
        int kase = 1;
        while(scanf("%d", &n) == 1 && n) 
        {
            trie.clear();
            for(int i = 0; i < n; i++)
            {
                scanf("%s", word);
                trie.insert(word);
            }
            printf("Case %d: %lld
    ", kase++, trie.count());
        }
        return 0;
    }
  • 相关阅读:
    使用tcmalloc编译启动时宕机
    使用tcmalloc编译出现undefined reference to `sem_init'
    使用AddressSanitizer做内存分析(一)——入门篇
    VIM-美化你的标签栏
    Entity Framework Code First (六)存储过程
    Entity Framework Code First (五)Fluent API
    Entity Framework Code First (四)Fluent API
    Entity Framework Code First (三)Data Annotations
    Entity Framework Code First (二)Custom Conventions
    Entity Framework Code First (一)Conventions
  • 原文地址:https://www.cnblogs.com/xiong-/p/3626221.html
Copyright © 2011-2022 走看看