zoukankan      html  css  js  c++  java
  • UVALive 5913 字典树

    先输入n个字符串的字典,每个字符串的前缀+后缀可以组成新的合法字符串,但肯定是有重复的,问从给定的字符串,生成的所有可能的字符串为多少个

    把前缀和后缀压入字典树,达到前缀和后缀的去重,首先的总和即为前缀数目乘以后缀数目,之后为了去重,记录每个前后缀非第一个相同的每个字母,则每个相同字母必定会产生重复。减掉即可。。还要注意,len=1的字符串特判。。注意细节处理

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    int n;
    LL sum1,sum2;
    LL num1[26],num2[26];
    struct node
    {
        int ch[400000][26];
        int cnt;
        void init()
        {
            memset(ch,0,sizeof ch);
            cnt=1;
        }
        void inserts(char* str)
        {
            int rt=0;
            int k=0;
            while (str[k])
            {
                int q=str[k]-'a';
                if (ch[rt][q]==0){
                    ch[rt][q]=cnt++;
                    sum1++;
                    if (k>0) num1[q]++;
                }
                rt=ch[rt][q];
                k++;
            }
        }
        void inserts2(char* str)
        {
            int rt=0;
            int k=0;
            while (str[k])
            {
                int q=str[k]-'a';
                if (ch[rt][q]==0){
                    ch[rt][q]=cnt++;
                    sum2++;
                    if (k>0) num2[q]++;
                }
                rt=ch[rt][q];
                k++;
            }
        }
    }T1,T2;
    char s[50];
    int len;
    int one[26];
    int main()
    {
    
        while (scanf("%d",&n)!=EOF)
        {
            T1.init();
            T2.init();
            sum1=sum2=0;
            memset(one,0,sizeof one);
            memset(num1,0,sizeof num1);
            memset(num2,0,sizeof num2);
            for (int i=0;i<n;i++){
                scanf("%s",s);
                T1.inserts(s);
                len=strlen(s);
                if (len==1) {one[s[0]-'a']=1;}
                reverse(s,s+len);
                T2.inserts2(s);
            }
            LL ans=sum1*sum2;
            //cout<<sum1<<" "<<sum2<<endl;
            for (int i=0;i<26;i++){
                if (one[i]) ans++;
                ans-=num1[i]*num2[i];
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    

      

  • 相关阅读:
    算法之美_源码公布(5)
    SDL2源码分析2:窗体(SDL_Window)
    hdu5303Delicious Apples
    Android之怎样给ListView加入过滤器
    EntboostChat 0.9(越狱版)公布,iOS免费企业IM
    unix关于打包命令zip的使用
    用 query 方法 获得xml 节点的值
    用友ERP T6技术解析(六) 库龄分析
    [笔试题] 两个有趣的问题
    使用SecueCRT在本地主机与远程主机之间交互文件
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3855473.html
Copyright © 2011-2022 走看看