一个计数问题构造trie解决
此处val域统计的是出现次数
由于空间紧张需要使用左儿子右兄弟表示方法
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#define SF scanf
#define PF printf
#define max(a, b) ((a) < (b) ? (b) : (a))
using namespace std;
typedef long long LL;
const int MAXN = 1000;
const int MAXL = 4000000;
const int SZ = 26;
char s[MAXN+10];
LL ans, Ncnt;
struct Trie_Tree
{
int son[MAXL+10], bro[MAXL+10], val[MAXL+10], cnt[MAXL+10];
char ch[MAXL+10];
void init() { val[0] = son[0] = bro[0] = 0; }
void insert(char *s)
{
ans += val[0];
val[0]++;
int u = 0, v, n = strlen(s);
for(int i = 0; i < n; i++)
{
bool ok = false;
for(v = son[u]; v; v = bro[v]) if(ch[v] == s[i]) { ok = true; break; }
if(!ok) {
v = ++Ncnt;
val[v] = cnt[v] = son[v] = 0;
ch[v] = s[i]; bro[v] = son[u]; son[u] = v;
}
u = v;
ans += val[u] * 2;
val[u]++;
}
if(cnt[v]) ans += cnt[v];
cnt[v]++;
}
}trie;
int main()
{
int n;
int kase = 0;
char t[110];
while(SF("%d", &n) && n)
{
ans = Ncnt = 0;
trie.init();
for(int i = 1; i <= n; i++) SF("%s", s), trie.insert(s);
PF("Case %d: %lld\n", ++kase, ans);
}
return 0;
}