P210
注意:字符串的量非常大,用二维的字典树会爆内存
用兄弟节点+儿子节点的字典树以时间换空间
一个节点有子节点和兄弟节点
对于节点u:son[u]为其子节点。
nexts[u] 为u的兄弟节点(相当于一个单链表)
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define ll long long
#define maxnode 4000010
ll ans;
struct Trie
{
char ch[maxnode];
int son[maxnode],nexts[maxnode],size;
int Have_word[maxnode];
int val[maxnode];
void init(){
size = 1;
memset(son, 0, sizeof(son)); memset(nexts, 0, sizeof(nexts)); memset(ch, 0, sizeof(ch)); memset(Have_word, 0, sizeof(Have_word)); memset(val, 0, sizeof(val));
}
void insert(char *s){
int u = 0, v, len = strlen(s);
for(int i = 0; i <= len; i++)
{
bool find = false, big = false;
for(v = son[u]; v; v = nexts[v])
if(ch[v] == s[i]){ find = true; break; }
if(find == false)
{
v = size++;
nexts[v] = son[u];
son[u] = v;
ch[v] = s[i];
}
ans += (val[u]-val[v])*(i<<1|1);
if(i == len)
{ ans+=val[v]*((i+1)<<1); val[v]++; }
val[u]++;
u = v;
}
Have_word[u]++;
}
}ac;
int n;
char s[1005];
int main(){
int Cas = 1;
while(scanf("%d",&n), n){
ac.init();
ans = 0;
while(n--)
{
scanf("%s",s);
ac.insert(s);
}
printf("Case %d: %lld\n",Cas++,ans);
}
}
/*
2
0
0
3
sadf156A
aAS
05sf4s5dfS
3
aZZ
AZZ
AZZ
3
AZZ
AZZ
aZZ
4
ABCD
ABC
ABCD
ABD
2
abcd
abc
*/