• UVA


    字典树问题

    对于普通的字典树,可以加一个vector数组记录非空的孩子,加快速度

    还可以用左孩子右兄弟来节省空间,因为普通的trie的话是

    int next[MAXN][26]

    而左孩子右兄弟可以把[26]省掉,这题实际上并不需要这么节省也可以AC

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<vector>
     6 #define MAXN 4000*1000+10
     7 #define ll long long
     8 using namespace std;
     9 struct Trie{
    10     int nxt[MAXN][65];
    11     int v[MAXN];
    12     vector<int> son[MAXN];
    13     int tot;
    14     int newnode(){
    15         tot++;
    16         memset(nxt[tot],0,sizeof(nxt[tot]));
    17         v[tot]=0;
    18         son[tot].clear();
    19         return tot;
    20     }
    21     void init(){
    22         tot=0;
    23         newnode();
    24     }
    25     int ind(char c){
    26         if('0'<=c&&c<='9') return c-48;
    27         else if('a'<=c&&c<='z') return c-87;
    28         else return c-29;
    29     }
    30     void insert(char s[]){
    31         int p=1;
    32         int len=strlen(s);
    33         for(int i=0;i<len;i++){
    34             int t=ind(s[i]);
    35             if(nxt[p][t]){
    36                 p=nxt[p][t];
    37             }
    38             else{
    39                 nxt[p][t]=newnode();
    40                 son[p].push_back(t);
    41                 p=nxt[p][t];
    42             }
    43         }
    44         v[p]++;
    45     }
    46     pair<ll,int> find(int p,int dep){
    47         ll ret=1LL*(v[p])*(v[p]-1)*(dep+1);
    48         int cnt=0;
    49         for(int i=0;i<son[p].size();i++){
    50             int tt=son[p][i];
    51             if(nxt[p][tt]){
    52                 pair<ll,int> t=find(nxt[p][tt],dep+1);
    53                 ret+=t.first;
    54                 ret+=1LL*cnt*t.second*(2*dep+1);
    55                 cnt+=t.second;
    56             }
    57         }
    58         ret+=1LL*cnt*(v[p])*(2*dep+1);
    59         cnt+=v[p];
    60         return make_pair(ret,cnt);
    61     }
    62 }D;
    63 int n;
    64 char s[1005];
    65 int main()
    66 {
    67     int T;
    68     while(1){
    69         scanf("%d",&n);
    70         if(!n)break;
    71         D.init();
    72         for(int i=1;i<=n;i++){
    73             scanf("%s",s);
    74             D.insert(s);
    75         }    
    76         printf("Case %d: %lld
    ",++T,D.find(1,0).first);
    77     }
    78     return 0;
    79 }
    普通字典树
     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<algorithm>
     4 #include<cstring>
     5 #include<vector>
     6 #define MAXN 4000*1000+10
     7 #define ll long long
     8 using namespace std;
     9 struct Trie{
    10     int first[MAXN];
    11     int nxt[MAXN];
    12     int v[MAXN];
    13     char ch[MAXN];
    14     int cnt;
    15     int newnode(int fa,char c){
    16         nxt[++cnt]=first[fa];
    17         first[fa]=cnt;
    18         first[cnt]=0;
    19         v[cnt]=0;
    20         ch[cnt]=c;
    21         return cnt;
    22     }    
    23     void init(){
    24         cnt=1;
    25         first[1]=nxt[1]=v[1]=ch[1]=0;
    26     }
    27     void insert(char s[]){
    28         int p=1;
    29         int len=strlen(s);
    30         for(int i=0;i<len;i++){
    31             int ok=0;
    32             for(int j=first[p];j;j=nxt[j]){
    33                 if(ch[j]==s[i]){
    34                     ok=1;
    35                     p=j;
    36                     break;
    37                 }
    38             }
    39             if(!ok){
    40                 p=newnode(p,s[i]);
    41             }
    42         }
    43         v[p]++;
    44     }
    45     pair<ll,int> find(int p,int dep){
    46         ll ret=1LL*(v[p])*(v[p]-1)*(dep+1);
    47         int cnt=0;
    48         for(int i=first[p];i;i=nxt[i]){
    49             pair<ll,int> t=find(i,dep+1);
    50             ret+=t.first;
    51             ret+=1LL*cnt*t.second*(2*dep+1);
    52             cnt+=t.second;
    53         }
    54         ret+=1LL*cnt*(v[p])*(2*dep+1);
    55         cnt+=v[p];
    56         return make_pair(ret,cnt);
    57     }
    58 }T;
    59 int n;
    60 char s[1005];
    61 int main()
    62 {
    63 //    freopen("data.in","r",stdin);
    64     int kase=0;
    65     while(1){
    66         scanf("%d",&n);
    67         if(!n)break;
    68         T.init();
    69         for(int i=1;i<=n;i++){
    70             scanf("%s",s);
    71             T.insert(s);
    72         }
    73         printf("Case %d: %lld
    ",++kase,T.find(1,0).first);
    74     }    
    75     return 0;
    76 }
    左孩子右兄弟
  • 相关阅读:
    遮罩层点击空白退出代码
    不同浏览器的margin值与padding值
    让div自适应浏览器窗口居中显示
    导航相关(下方导航指示条居中)
    CSS相邻兄弟选择器
    使用font-size:0去掉inline-block元素之间的空隙
    box-sizing属性
    常见浏览器兼容性问题
    秋季编程总结
    POJ 1193 内存分配
  • 原文地址:https://www.cnblogs.com/w-h-h/p/7901978.html
Copyright © 2020-2023  润新知