zoukankan      html  css  js  c++  java
  • UVA 11732 "strcmp()" Anyone? (Trie)

    题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2832


    题意:模拟strcmp()函数,给n个字符串,两两之间进行比較,问须要进行多少次比較?

    解析:字符串非常多,数据量大。按题意两两比較显然不现实。假设把全部的单词插入到一棵Trie里面会怎么样呢?考虑than和that相应的结点,than和that的前3个字符是一样的,但第4个字符不同。因此比較次数是7。不仅如此,不论什么两个在同一结点处分叉的字符串都须要比較7次。



    AC代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxnode = 4000 * 1000 + 5;
    const int sigma_size = 26;
    
    struct Trie{    //因为字符集较大,故用左儿子-右兄弟表示法保存
        int head[maxnode];   //左儿子编号
        int next[maxnode];   //右兄弟编号
        char ch[maxnode];    //结点上的字符
        int tot[maxnode];    //以该结点为根的结点总数
        int sz;
        long long ans;
    
        void clear(){ sz = 1; tot[0] = head[0] = next[0] = 0; }  //初始仅仅有一个根结点
    
        void insert(const char *s){
            int u = 0, v, n = strlen(s);
            tot[0] ++;
            for(int i=0; i<=n; 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];
                    head[u] = v;   //插到链表首部
                    head[v] = 0;
                }
                u = v;
                tot[u] ++;
            }
        }
    
        // 统计LCP=u的全部单词两两的比較次数之和
        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]); // 子树v中选一个串,其它子树中再选一个
              ans += sum / 2 * (2 * depth + 1);    // 每种选法统计了两次。故除2
              for(int v = head[u]; v != 0; v = next[v])
                dfs(depth+1, v);
            }
        }
    
        // 统计
        long long count() {
            ans = 0;
            dfs(0, 0);
            return ans;
        }
    
    };
    
    Trie T;
    
    int main(){
        #ifdef sxk
            freopen("in.txt", "r", stdin);
        #endif // sxk
    
        int n, t = 0;
        char s[1002];
        while(scanf("%d", &n) != EOF && n){
            T.clear();
            for(int i=0; i<n; i++){
                scanf("%s", s);
                T.insert(s);
            }
            printf("Case %d: %lld
    ", ++t, T.count());
        }
        return 0;
    }
    




  • 相关阅读:
    Python汉字转换成拼音
    python之Tkinter控件学习
    python 函数式编程:高阶函数,map/reduce
    python的高级特性:切片,迭代,列表生成式,生成器,迭代器
    python tkinter Listbox用法
    python函数定义语法总结
    Cmder 快捷键
    录音水波动画
    图片截取部分显示
    移动web在ios和android下点击元素出现阴影问题
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7290164.html
Copyright © 2011-2022 走看看