• uva 11732


    字典树;

    不过数据量很大;4000*1000;

    我用的是传统的方法建树,虽然优化了一下,边插入边统计,不过还是T了;

    这是我的代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #define maxn 4000009
     4 using namespace std;
     5 int nonocount;
     6 long long ans;
     7 struct node
     8 {
     9     int num;
    10     node *a[62];
    11 } no[maxn];
    12 
    13 node* newnode()
    14 {
    15     node *p=no+nonocount++;
    16     p->num=0;
    17     memset(p->a,NULL,sizeof p->a);
    18     return p;
    19 }
    20 
    21 void insert(node *root,char *s)
    22 {
    23     int l=strlen(s);
    24     for(int i=0; i<l; i++)
    25     {
    26         int x;
    27         if(s[i]>='0'&&s[i]<='9')x=s[i]-'0';
    28         else if(s[i]>='a'&&s[i]<='z')x=s[i]-'a'+10;
    29         else if(s[i]>='A'&&s[i]<='Z')x=s[i]-'A'+36;
    30         if(root->a[x]==NULL)
    31             root->a[x]=newnode();
    32         ans+=(root->num)-(root->a[x]->num);
    33         root->num++;
    34         root=root->a[x];
    35     }
    36 }
    37 char s[1005];
    38 int main()
    39 {
    40     int n,ca=1;
    41     while(scanf("%d",&n)&&n)
    42     {
    43         nonocount=0;
    44         node *p=newnode();
    45         ans=0;
    46         for(int i=0; i<n; i++)
    47         {
    48             scanf("%s",s);
    49             insert(no,s);
    50         }
    51         printf("Case %d: %lld
    ",ca++,ans);
    52     }
    53     return 0;
    54 }
    View Code

    网上的大神的方法是采用左儿子右兄弟的方法建树;

    这样节省了很多的时间,受教了!

    大神的代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 const int maxnode = 4000*1000;
     7 struct trie
     8 {
     9     int left[maxnode]; // 左儿子
    10     int right[maxnode]; // 右兄弟
    11     int val[maxnode] ; //该节点上有多少串
    12     char ch[maxnode]; // 节点表示的字符
    13     int cnt ;
    14     long long int ans ;
    15     void init()
    16     {
    17         ch[0] = 0, left[0] = right[0] = 0;
    18         val[0] = 0;
    19         cnt = 1;
    20         ans = 0;
    21     }
    22     void insert(const char *s)
    23     {
    24         int len = strlen(s) , u = 0,j;
    25         for(int i = 0; i <= len ; ++i )
    26         {
    27             for(j = left[u]; j ; j = right[j])if(ch[j] == s[i]) break; //找到这个节点
    28             if(j==0)
    29             {
    30                 j = cnt++;
    31                 ch[j] = s[i];
    32                 right[j] = left[u];
    33                 left[j] = 0;
    34                 left[u] = j;
    35                 val[j] = 0;
    36             }
    37             ans += (val[u] - val[j])*(i << 1|1);
    38             if(i == len)
    39             {
    40                 ans += val[j]*((i+1)<<1);    //特判结尾 Trie中不会进入结尾字符,需特判统计
    41                 val[j]++;
    42             }
    43             val[u]++;
    44             u = j;
    45         }
    46     }
    47 } Tri;
    48 char tmp[2000];
    49 int main()
    50 {
    51     int n,kase = 1 ;
    52     while(scanf("%d",&n)==1 && n)
    53     {
    54         Tri.init();
    55         for(int k=0; k<n; ++k)
    56         {
    57             scanf("%s",tmp);
    58             Tri.insert(tmp);
    59         }
    60         printf("Case %d: %lld
    ", kase++, Tri.ans);
    61     }
    62     return 0;
    63 }
    View Code
  • 相关阅读:
    C#编程技巧之钩子函数的使用——SetWindowsHookEx
    JSON(Ajax)和JsonP
    C#对象与方法
    C#数据类型
    事务处理
    面向对象之继承与多态
    C#编程语言简介
    <转>成员函数的重载、覆盖与隐藏
    视图、索引
    C#方法
  • 原文地址:https://www.cnblogs.com/yours1103/p/3396635.html
Copyright © 2020-2023  润新知