一開始不知道这样的一维建树方法。
每次一层用一个链指向下一层最左边的结点,之后每一层用一个链表串联全部的结点,这样就建树成功了。
14328524 | 11732 | strcmp() Anyone? | Accepted | C++ | 0.826 | 2014-10-09 13:13:14 |
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; typedef pair<int,int> pill; const int nodemaxn = 4000 * 1000 + 100; struct Trie{ int head[nodemaxn]; //左儿子链 int next[nodemaxn]; //右兄弟链 int ch[nodemaxn]; //这个结点代表的字符 LL tot[nodemaxn]; //有几个单词经过了这个结点 int sz; //结点个数 LL ret; //比較的次数 void clear(){ head[0] = 0; next[0] = 0; tot[0] = 0; sz = 1; ret = 0; } void insert(char *str){ int L = strlen(str); int u = 0,v,found; tot[0]++; for(int i = 0; i <= L; i ++){ found = 0; for(v = head[u]; v != 0 ; v = next[v]){ //到下一层去找 if(ch[v] == str[i]){ found = 1; break; } } if(!found){ //假设没有找到 v = sz ++; tot[v] = 0; ch[v] = str[i]; next[v] = head[u]; head[u] = v; head[v] = 0; } u = v; tot[u] ++; } } void dfs(int u,int depth){ if(head[u] == 0){ ret += tot[u] * (tot[u] - 1) * depth; } else{ LL sum = 0; for(int v = head[u] ; v != 0; v = next[v]) sum += tot[v] * (tot[u] - tot[v]); ret += sum / 2 * (2 * depth + 1); for(int v = head[u] ; v != 0; v = next[v]) dfs(v,depth + 1); } } }trie; const int maxn = 4000 + 10; int main(){ int n,Case = 1; while(scanf("%d",&n) && n){ trie.clear(); for(int i = 0; i < n; i++){ char str[maxn]; scanf("%s",str); trie.insert(str); } trie.dfs(0,0); printf("Case %d: %lld ",Case++,trie.ret); } }