[UVa 11732] "strcmp()"Anyone?
Posted newera
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[UVa 11732] "strcmp()"Anyone?相关的知识,希望对你有一定的参考价值。
Link:
Solution:
思路还是很套路:建$Trie$树,在$Trie$树上跑一遍统计答案
(统计答案时注意将叶节点特殊处理,同时对于$e(u,v)$用$val[v]*(val[u]-val[v])$来统计个数)
重点在于此题的存储方式:左儿子右兄弟存储法 (链表式存储法)
由于此题节点数$MAXN=4e6$,如果按照$ch[MAXN][27]$建图刚好$MLE$
而链表式存储法优点就在于省空间,不用建立多余的节点,只不过牺牲了查询的效率
实现起来很像链式前向星:$ls[i]$相当于$head[i]$,$rb[i]$相当于$nxt[i]$,每次插入也是从头部插入
Tip:在处理过程中将数据初始化,尽量不用$memset$
Code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=4e6+10; char s[1005],ch[MAXN];ll res=0; int T,n,ls[MAXN],rb[MAXN],val[MAXN],cnt=0; void insert() { int len=strlen(s); int u=0,v;val[0]++; for(int i=0;i<=len;i++) { bool f=false; for(v=ls[u];v;v=rb[v]) if(ch[v]==s[i]){f=true;break;} if(!f) { v=++cnt;ch[v]=s[i]; //建立新节点 rb[v]=ls[u];ls[u]=v; ls[v]=0;val[v]=0; } u=v;val[u]++; } } void dfs(int dep,int u) { if(!ls[u]){res+=1ll*val[u]*(val[u]-1)*dep;return;} //统计叶节点的答案 ll sum=0;int v; for(v=ls[u];v;v=rb[v]) //统计答案 sum+=val[v]*(val[u]-val[v]); res+=1ll*sum/2*(2*dep+1); for(v=ls[u];v;v=rb[v]) dfs(dep+1,v); } int main() { while(scanf("%d",&n)==1 && n) { cnt=0;val[0]=ls[0]=rb[0]=0; for(int i=1;i<=n;i++) scanf("%s",s),insert(); res=0;dfs(0,0); printf("Case %d: %lld ",++T,res); } return 0; }
以上是关于[UVa 11732] "strcmp()"Anyone?的主要内容,如果未能解决你的问题,请参考以下文章
UVa 11732 "strcmp()" Anyone? (左儿子右兄弟前缀树Trie)