[UVa 11732] "strcmp()"Anyone?
阿新 • • 發佈:2018-06-30
print clu any TP head cas mes 處理 scan 插入
Link:
UVa 11732 傳送門
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\n",++T,res); } return 0; }
[UVa 11732] "strcmp()"Anyone?