刘汝佳蓝书上说这题字符集较大,所以我先是尝试用了指针写法,然而总是TLE。看了看题解数组写法能过,改用数组写法就AC了。为什么呢?
指针写法
#include <stdio.h>
#include <string.h>
typedef long long ll;
ll ans;
struct node{
int end, cnt;
node *son[63];
};
node *root;
int num(char ch) {
if (ch >= 'a' && ch <= 'z') return ch - 'a';
if (ch >= 'A' && ch <= 'Z') return 26 + ch - 'A';
return 52 + ch - '0';
}
void insert(char *s) {
int len = strlen(s);
node *u = root;
for (int i = 0; i < len; ++i) {
int ch = num(s[i]);
if (u->son[ch] == NULL) u->son[ch] = new node();
ans += (u->cnt - u->son[ch]->cnt) * (2 * i + 1);
u->cnt++;
u = u->son[ch];
}
ans += (u->cnt - u->end) * (2 * len + 1);
ans += u->end * 2 * (len + 1);
u->cnt++;
u->end++;
}
int main() {
int n, T = 0;;
char s[1010];
while (~scanf("%d", &n) && n) {
ans = 0;
root = new node();
while (n--) {
scanf("%s", s);
insert(s);
}
printf("Case %d: %lld\n", ++T, ans);
}
return 0;
}
数组写法
#include <stdio.h>
#include <string.h>
typedef long long ll;
const int MAXN = 4e6 + 10;
int tot = 1, trie[MAXN][63], cnt[MAXN], end[MAXN];
ll ans;
int num(char ch) {
if (ch >= 'a' && ch <= 'z') return ch - 'a';
if (ch >= 'A' && ch <= 'Z') return 26 + ch - 'A';
return 52 + ch - '0';
}
void insert(char *s) {
int u = 1, len=strlen(s);
for (int i = 0; i < len; ++i) {
int ch = num(s[i]);
if (!trie[u][ch]) trie[u][ch] = ++tot;
ans += (cnt[u] - cnt[trie[u][ch]]) * (2 * i + 1);
cnt[u]++;
u = trie[u][ch];
}
ans += (cnt[u] - end[u]) * (2 * len + 1);
ans += end[u] * 2 * (len + 1);
cnt[u]++;
end[u]++;
}
int main() {
int n, T = 0;
char s[1010];
while (~scanf("%d", &n) && n) {
memset(trie, 0, sizeof(trie));
memset(end, 0, sizeof(end));
memset(cnt, 0, sizeof(cnt));
ans = 0;
tot = 1;
while (n--) {
scanf("%s", s);
insert(s);
}
printf("Case %d: %lld\n", ++T, ans);
}
return 0;
}