字典树问题
对于普通的字典树,可以加一个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 }