• bzoj3806: Neerc2011 Dictionary Size


    Description

    某国颁布了一本 n (n ≤ 10 000) 个单词的词典。单词长
    度不超过 40。 
    该国的造词法是这样的: 
    1: 词典中的单词是一个词。 
    2: 能分为两部分的,其中前一部分是一个词典词或者其非
    空前缀,后一部分是一个词典词或者其非空后缀的词。 
    求能造出的不相同的词汇数目。 

    将所有单词建成trie(A),反转后也建一颗trie(B),答案有三种情况

    1.原有单词

    2.原有单词的 长度>1的 严格前缀,且其最后一个字母是某单词的首字母

    3.不是原有单词或其前缀,但可以由前缀和后缀拼出(由于可能重复,对一个由两个单词拼出的串只统计后缀最短的一个,)

    分类统计即可

    #include<cstdio>
    #include<cstring>
    typedef long long i64;
    const int N=400007;
    i64 ans=0;
    char ss[10007][43];
    int n,ch[N][26],p1=1,p2=1,t0[26],t1[26],t2[26];
    int*ed[N];
    bool e[N],ee[26];
    int main(){
        scanf("%d",&n);
        for(int t=0;t<n;++t){
            scanf("%s",ss[t]);
            int l=strlen(ss[t]),w=1,c;
            for(int i=0;i<l;++i){
                c=ss[t][i]-'a';
                int &u=ch[w][c];
                if(!u)ed[u=++p1]=&u,++t1[c];
                w=u;
            }
            ee[c]=1;
            if(!e[w]){
                if(l>1)--t0[c];
                e[w]=1;
                ++ans;
            }
        }
        for(int i=0;i<26;++i)if(ch[1][i])--t1[i];
        for(int i=0;i<26;++i)if(ee[i])ans+=t0[i]+t1[i];
        for(int i=2;i<=p1;++i)*ed[i]=0;
        for(int t=0;t<n;++t){
            int l=strlen(ss[t]),w=1;
            for(int i=l-1;i>=0;--i){
                int c=ss[t][i]-'a',&u=ch[w][c];
                if(!u)u=++p2,++t2[c];
                w=u;
            }
        }
        ans+=i64(p1-1)*(p2-1);
        for(int i=0;i<26;++i)ans-=i64(t1[i])*t2[i];
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    重新把指针学习一边。。。
    是走协议这条路呢,还是软件开发这条路呢,这是个问题
    mfc缺少rc.2文件解决办法
    ipad安装siri成功!!
    c语言声明变量和函数的探讨
    C# xml格式整理工具
    winxp登录到administrator界面操作方法
    [c]sprintf
    win7 64位 Ramdisk安装日志
    Kafka深度解析
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7009399.html
Copyright © 2020-2023  润新知