Files
SH-Quizzes/ACMOJ-2121.cpp
2024-04-18 18:38:55 +08:00

84 lines
2.4 KiB
C++

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
typedef long double LDB;
const int kMaxN = (1 << 20) + 10;
int T;
char s[kMaxN];
int z[kMaxN];
int suf_cnt[26], pre_cnt[26];
int tot_bucket[kMaxN];
inline void Flip(char ch, int *cnt, int &occur) {
cnt[ch - 'a'] ^= 1;
if (cnt[ch - 'a'])
occur++;
else
occur--;
}
LL solve() {
int n = strlen(s);
memset(z, 0, sizeof(z));
for (int i = 1, l = 0, r = 0; i < n; ++i) {
if (i <= r && z[i - l] < r - i + 1) {
z[i] = z[i - l];
} else {
z[i] = max(0, r - i + 1);
while (i + z[i] < n && s[z[i]] == s[i + z[i]]) ++z[i];
}
if (i + z[i] - 1 > r) l = i, r = i + z[i] - 1;
}
LL res = 0;
int even_A_tot = 0;
int odd_A_tot = 0;
memset(suf_cnt, 0, sizeof(suf_cnt));
for (int i = 0; i < n; i++) suf_cnt[s[i] - 'a'] ^= 1;
int all_occur_tot = 0, suf_occur_tot = 0, pre_occur_tot = 0;
for (int i = 0; i < 26; i++) all_occur_tot += suf_cnt[i];
memset(pre_cnt, 0, sizeof(pre_cnt));
suf_occur_tot = all_occur_tot;
Flip(s[0], suf_cnt, suf_occur_tot);
memset(tot_bucket, 0, sizeof(tot_bucket));
for (int i = 1; i <= n - 1; i++) {
int odd_C_tot = ceil((min(z[i], n - i - 1) / i + 1) / 2.0);
int even_C_tot = ((min(z[i], n - i - 1) / i + 1) / 2.0);
res += odd_A_tot * (LL)odd_C_tot;
res += even_A_tot * (LL)even_C_tot;
// printf("A(%d,%d)\n", odd_A_tot, odd_C_tot);
// printf("B(%d,%d)\n", even_A_tot, even_C_tot);
if (i == n - 1) break;
int old_suf_occur_tot = suf_occur_tot;
Flip(s[i], suf_cnt, suf_occur_tot);
// Flip(s[i - 1], pre_cnt, pre_occur_tot, tot_bucket);
pre_cnt[s[i - 1] - 'a'] ^= 1;
if (pre_cnt[s[i - 1] - 'a']) {
pre_occur_tot++;
} else {
pre_occur_tot--;
}
tot_bucket[pre_occur_tot]++;
if (pre_occur_tot <= old_suf_occur_tot) odd_A_tot++;
if (old_suf_occur_tot < suf_occur_tot)
odd_A_tot += tot_bucket[suf_occur_tot];
else
odd_A_tot -= tot_bucket[old_suf_occur_tot];
// printf("i=%d all_occur_tot=%d pre_occur_tot=%d suf_occur_tot=%d\n", i,
// all_occur_tot, pre_occur_tot, suf_occur_tot);
// odd_A_tot += (pre_occur_tot <= suf_occur_tot ? 1 : 0);
even_A_tot += (pre_occur_tot <= all_occur_tot ? 1 : 0);
}
return res;
}
int main() {
#ifdef local
freopen("pro.in", "r", stdin);
#endif
scanf("%d", &T);
while (T-- > 0) {
scanf("%s", s);
printf("%lld\n", solve());
}
return 0;
}