UVA - 11732:"strcmp()" Anyone?

字典树问题

对于普通的字典树,可以加一个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\n",++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\n",++kase,T.find(1,0).first);
74     }    
75     return 0;
76 }
左孩子右兄弟

 

转载于:https://www.cnblogs.com/w-h-h/p/7901978.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值