input
n 2<=n<=4000
s1
s2
...
sn
1<=len(si)<=1000
output
输出用strcmp()两两比较si,sj(i!=j)要比较的次数,结果在long long范围内(相同字符比较两次,不相同字符比较一次,包括'\0')
做法:由于字符集太大,要用左兄弟右儿子的trie保存字符,不用每次都开ch[62]个孩子
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <cstdio> 2 #include <queue> 3 #include <cstring> 4 #include <iostream> 5 #include <cstdlib> 6 #include <algorithm> 7 #include <vector> 8 #include <map> 9 #include <set> 10 #include <ctime> 11 #include <cmath> 12 #include <cctype> 13 #define MAX 100000 14 #define LL long long 15 #define mod 20071027 16 struct node 17 { 18 int sz; 19 char val; 20 node*ch[2]; //ch[1]兄弟,ch[0]儿子 21 node() 22 { 23 ch[0]=ch[1]=NULL; 24 sz=0; 25 } 26 }; 27 char word[1010]; 28 int n,cas=1; 29 long long sum; 30 long long insert(char*s,node*u) 31 { 32 long long sum=0,lastsz=u->sz++; 33 for(;*s||*(s-1);s++) 34 { 35 if(!u->ch[0]) //易错,要先把新建的结点连接到父结点才能往下走,否则新建之后父节点无法再读取到该结点 36 { 37 u->ch[0]=new node; 38 u->ch[0]->val=*s; 39 } 40 for(u=u->ch[0];u->val!=*s;u=u->ch[1]) 41 { 42 if(!u->ch[1]) 43 { 44 u->ch[1]=new node; 45 u->ch[1]->val=*s; 46 } 47 } 48 sum+=lastsz+u->sz; 49 lastsz=u->sz++; 50 } 51 return sum; 52 } 53 /*//这样可以将父节点的ch和新建的结点绑定起来,传过来的是&root 54 long long insert(char*s,node**u) 55 { 56 long long sum=0,lastsz=(*u)->sz++; 57 for(;*s||*(s-1);s++) 58 { 59 printf("%p\n",u); 60 for(u=&((*u)->ch[0]);(*u)&&(*u)->val!=*s;u=&((*u)->ch[1])); 61 if(*u==NULL) 62 { 63 *u=new node; 64 (*u)->ch[0]=(*u)->ch[1]=NULL; 65 (*u)->val=*s; 66 } 67 sum+=lastsz+(*u)->sz; 68 lastsz=(*u)->sz++; 69 } 70 return sum; 71 }*/ 72 void freenode(node*u) 73 { 74 if(u==NULL) return; 75 freenode(u->ch[0]); 76 freenode(u->ch[1]); 77 delete u; 78 } 79 int main() 80 { 81 //freopen("/home/user/桌面/in","r",stdin); 82 while(scanf("%d",&n)==1&&n) 83 { 84 sum=0; 85 node *root=new node; 86 while(n--) 87 { 88 scanf("%s",word); 89 sum+=insert(word,root); 90 } 91 printf("Case %d: %lld\n",cas++,sum); 92 freenode(root); 93 } 94 //printf("time=%.3lf",(double)clock()/CLOCKS_PER_SEC); 95 return 0; 96 } 97 98 my Code
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 using namespace std; 6 7 #define repf(i,a,b) for(int i=(a);i<=(b);i++) 8 typedef long long ll; 9 10 const int N = 0; 11 const int MAXNODE = 4000010; 12 13 int n, cas; 14 ll ans; 15 char str[4001]; 16 17 struct STrie { 18 int son[MAXNODE]; 19 int bro[MAXNODE]; 20 int val[MAXNODE]; 21 char ch[MAXNODE]; 22 int sz; 23 24 STrie() { sz = 1; ch[0] = val[0] = bro[0] = son[0] = 0; } 25 void init() { sz = 1; ch[0] = val[0] = bro[0] = son[0] = 0; } 26 // inline int idx(char c) { return c - 'a'; } 27 28 void insert(char *s) { 29 int len = strlen(s), u = 0, p; 30 repf (i, 0, len) { 31 // check the brother of u 32 for (p = son[u]; p; p = bro[p]) { 33 if (ch[p] == s[i]) 34 break; 35 } 36 // cannot find out than insert 37 if (!p) { 38 p = sz++; 39 ch[p] = s[i]; 40 bro[p] = son[u]; 41 son[p] = 0; 42 val[p] = 0; 43 son[u] = p; 44 } 45 ans += (val[u] - val[p]) * (2 * i + 1); 46 if (len == i) { 47 ans += val[p] * (2 * i + 2); 48 val[p]++; 49 } 50 val[u]++; 51 u = p; 52 } 53 } 54 } trie; 55 56 int main() { 57 // ios_base::sync_with_stdio(0); 58 while (~scanf("%d", &n) && n) { 59 trie.init(); 60 ans = 0; 61 repf (i, 0, n - 1) { 62 scanf("%s", str); 63 trie.insert(str); 64 } 65 printf("Case %d: %lld\n", ++cas, ans); 66 } 67 return 0; 68 }