题意:给出n个字符串,进行两两比较,计算比较的次数。
刚开始用指针写,发现这样写保存信息的时候不好计算,于是学习刘汝佳的儿子兄弟表示,这样建树统计分差点的比较次数是非常方便。
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
using namespace std;
const int maxn=4000*1000*10;
int n;
struct trie
{
int head[maxn];//第一个孩子节点编号
int next[maxn];//兄弟编号
int tot[maxn];//经过这个节点的字符串数量
char ch[maxn];
int sz;
long long ans;
void clear(){sz=1;ans=0;head[0]=next[0]=tot[0]=0;}
void insert(char * a)
{
int u=0,v,len=strlen(a);
tot[0]++;
for(int i=0;i<=len;i++)
{
bool found=false;
for(v=head[u];v!=0;v=next[v])
{
if(ch[v]==a[i])
{
found=true;
break;
}
}
if(!found)//找不到,新建节点
{
v=sz++;
tot[v]=0;
next[v]=head[u];
head[u]=v;
ch[v]=a[i];
head[v]=0;
}
u=v;
tot[u]++;
}
}
void dfs(int depth,int u)
{
if(head[u]==0)
{
ans+=tot[u]*(tot[u]-1)*depth;
return;
}
int sum=0;
for(int v=head[u];v!=0;v=next[v])
sum+=tot[v]*(tot[u]-tot[v]);
ans+=sum/2*(depth*2+1);
for(int v=head[u];v!=0;v=next[v])
dfs(depth+1,v);
}
long long count()
{
ans=0;
dfs(0,0);
return ans;
}
}tree;
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int t=1;
while(scanf("%d",&n)!=EOF,n)
{
char a[4010];
tree.clear();
for(int i=0;i<n;i++)
{
scanf("%s",a);
tree.insert(a);
}
printf("Case %d: %lld\n",t++,tree.count());
}
return 0;
}