84 lines
2.4 KiB
C++
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;
|
|
} |