题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68198#problem/B
题意:给出n个字符串, 计算两两比较的次数,注意两字符相等情况下需要比较(str1[i] == str2[i])和 (str1[i] == '\0'各一次).
思路:将所有单词插到一棵trie上,不过这题数据量很大,故采用左儿子右兄弟写法
#include <cstdio>
#include <cstring>
#include <queue>
#include <stack>
#include <functional>
#include <utility>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <set>
#include <cmath>
#include <stdlib.h>
#include <climits>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#pragma comment (linker, "/STACK:1024000000,1024000000")
typedef long long ll;
using namespace std;
const int maxn = 4010 * 1010;
struct trie
{
char ch[maxn];
int bro[maxn], son[maxn];
int val[maxn]; //记录经过这个点的单词有多少个
int sz;
long long ans;
void init()
{
ans = 0;
sz = 1;
ch[0] = 0;
son[0] = bro[0] = val[0] = 0;
}
void insert(char *s)
{
int p;
int n = strlen(s), u = 0;
for (int i = 0; i <= n; i++)
{
for (p = son[u]; p; p = bro[p])
{
if (s[i] == ch[p]) break;
}
if (!p)
{
p = sz++;
ch[p] = s[i];
bro[p] = son[u];
son[u] = p;
son[p] = 0;
val[p] = 0;
}
ans += (val[u] - val[p]) * (2 * i + 1);
if (i == n)
{
ans += val[p] * (2 * (i + 1));
val[p]++;
}
val[u]++;
u = p;
}
}
} tr;
char s[1010];
int main()
{
int n, ca = 1;
while (~scanf("%d", &n) && n)
{
tr.init();
for (int i = 0; i < n; i++)
{
scanf("%s", s);
tr.insert(s);
}
printf("Case %d: %lld\n", ca++, tr.ans);
}
return 0;
}