zoukankan      html  css  js  c++  java
  • UVA

    https://vjudge.net/problem/UVA-11732

    题意

    给定n个字符串,问用strcmp函数比较这些字符串共用多少次比较。

    strcmp函数的实现

    int strcmp(char *s, char *t)
    {
        int i;
        for (i=0; s[i]==t[i]; i++)
            if (s[i]=='')
                return 0;
        return s[i] - t[i];
    }

    分析

    建trie树,把‘’也加进去,记录以每个节点为子树包含的单词节点。

    然后dfs计数,遇到单词节点,说明可能存在相同的字符串,于是此时ans+=tot[u]*(tot[u]-1)*dep;

    否则就是(2*dep+1)*sum,sum为所有选法。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <cmath>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <stack>
    #include <set>
    #include <bitset>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    #define ms(a, b) memset(a, b, sizeof(a))
    #define pb push_back
    #define mp make_pair
    #define pii pair<int, int>
    //#define eps 0.0000000001
    #define IOS ios::sync_with_stdio(0);cin.tie(0);
    #define random(a, b) rand()*rand()%(b-a+1)+a
    #define pi acos(-1)
    //const ll INF = 0x3f3f3f3f3f3f3f3fll;
    const int inf = 0x3f3f3f3f;
    const int maxn = 4000 * 1000 + 10;
    const int maxm = 4e5 +10;
    const int mod = 20071027;
    const int sigma_size = 26;
    
    struct Trie{
        int head[maxn];// head[i]为第i个结点的左儿子编号
        int nxt[maxn];// next[i]为第i个结点的右兄弟编号
        char ch[maxn];// ch[i]为第i个结点上的字符
        int tot[maxn];// tot[i]为第i个结点为根的子树包含的叶结点总数
        int sz;
        ll ans;// 答案
        void init(){
            sz=1;
            tot[0]=head[0]=nxt[0]=0;
        }
        // 插入字符串s(包括最后的''),沿途更新tot
        void insert(char* s){
            int u=0,v,n=strlen(s);
            tot[0]++;
            for(int i=0;i<=n;i++){
                // 找字符a[i]
                bool f=false;
                for(v=head[u];v;v=nxt[v]){
                    if(ch[v]==s[i]){// 找到了
                        f=true;
                        break;
                    }
                }
                if(!f){
                    v=sz++;// 新建结点
                    tot[v]=0;
                    ch[v]=s[i];
                    nxt[v]=head[u];
                    head[u]=v;// 插入到链表的首部
                    head[v]=0;
                }
                u = v;
                tot[u]++;
            }
        }
          // 统计LCP=u的所有单词两两的比较次数之和
        void dfs(int dep,int u){
            // 叶结点
            if(head[u]==0) ans+=tot[u]*(tot[u]-1)*dep;
            else{
                int sum=0;
                for(int v=head[u];v;v=nxt[v]){
                    sum+=tot[v]*(tot[u]-tot[v]);
                    // 子树v中选一个串,其他子树中再选一个
                }
                // 除以2是每种选法统计了两次
                ans+=sum/2*(2*dep+1);
                for(int v=head[u];v;v=nxt[v])
                    dfs(dep+1,v);
            }
        }
        ll cal(){
            ans=0;
            dfs(0,0);
            return ans;
        }
    };
    Trie trie;
    char tmp[1010];
    int main() {
    #ifdef LOCAL
        freopen("in.txt", "r", stdin);
    //    freopen("input.txt", "w", stdout);
    #endif
        int cas=1;
        int T;
        while(~scanf("%d",&T)&&T){
            trie.init();
            for(int i=0;i<T;i++){
                scanf("%s",tmp);
                trie.insert(tmp);
            }
            printf("Case %d: %lld
    ",cas++,trie.cal());
        }
        return 0;
    }
  • 相关阅读:
    KMP算法之查找模式串在源串中出现的次数
    快速排序算法分析
    排序算法的稳定性分析(转)
    动态规划之最优二叉搜索树(算法导论)
    动态规划之最长公共子序列(算法导论)
    动态规划原理(算法导论)
    动态规划之钢条切割(算法导论)
    动态规划之矩阵链相乘问题(算法导论)
    HNU 13064 Cuckoo for Hashing解题报告 North America
    HNU 13081 Even Up Solitaire解题报告
  • 原文地址:https://www.cnblogs.com/fht-litost/p/9627758.html
Copyright © 2011-2022 走看看