给你n个单词,让他们两两比较,要求他们运用strcmp时,进行比较的次数。
边建树边统计
#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define rap(i, a, n) for(int i=a; i<=n; i++)
#define rep(i, a, n) for(int i=a; i<n; i++)
#define lap(i, a, n) for(int i=n; i>=a; i--)
#define lep(i, a, n) for(int i=n; i>a; i--)
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _ ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int maxn = , INF = 0x7fffffff;
int trie[maxn][], sum[maxn], isend[maxn];
string str;
int rt, tot;
LL ans; int idx(char s){
if(s >= '' && s <= ''){
return s - '';
} else if(s >= 'A' && s <= 'Z'){
return + s - 'A';
} else{
return + s - 'a';
} } void build()
{
int len = str.size();
rt = ;
for(int i=; i<len; i++)
{
int x = idx(str[i]);
if(trie[rt][x] == )
{
ans += sum[rt] * ( * i + ); //如果不存在这个字母 则与这个字母前的所有前缀都不同
trie[rt][x] = ++tot;
}
else
ans += (sum[rt] - sum[trie[rt][x]]) * ( * i + ); //如果存在这个字母 则只与在这个位置上和这个字母不相同的 不同
sum[rt]++; //这种写法是从祖结点开始算的 可以返回不同单词的个数 即sum[0]
rt = trie[rt][x];
}
ans += isend[rt] * * (len + ); //因为有\0所以是len+1
ans += (sum[rt] - isend[rt]) * ( * len + );
sum[rt]++;
isend[rt]++;
} void init()
{
tot = ans = ;
mem(isend, );
mem(sum, );
mem(trie, );
} int main()
{
int n, kase = ;
while(~scanf("%d", &n) && n)
{
init();
rap(i, , n)
{
cin>> str;
build();
}
printf("Case %d: ", ++kase);
cout<< ans <<endl; } return ;
}