# 思路

G[i - r[i]].push_back(i);//G[这个位置开始的].push_back(覆盖到哪里);

ans += sum（当前i的边界 - i）；//满足上式的区段

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<cstring>

using namespace std;
const int MaxN = 1e6 + 5;
typedef long long LL;

int t,n,p[MaxN],tree[MaxN],r[MaxN];
char s[MaxN],S[MaxN];

vector<int> G[MaxN];

void getS(){
n = strlen(s + 1);
S[0] = '@';
for(int i = 1;i <= n; i++){
S[i * 2 - 1] = '#';
S[i * 2] = s[i];
}
S[n * 2 + 1] = '#';
S[n * 2 + 2] = '\$';
n = n * 2 + 2;
}

void manachar(){
int mx = 0,C = 0,ans = 0;
for(int i = 1;i < n; i++){
if(mx > i) p[i] = min(mx - i,p[2 * C - i]);
else p[i] = 1;
while(S[i + p[i]] == S[i - p[i]]) p[i]++;
if(p[i] + i > mx){
mx = p[i] + i;
C = i;
//			if(p[i] > ans){
//				ans = p[i];
//				A = i;
//			}
}
}
}

void update(int x){
for(int i = x;i <= n; i += i & (-i)){
tree[i] += 1;
}
}

LL sum(int x){
LL cur = 0;
for(int i = x;i;i -= i & (-i)){
cur += tree[i];
}
return cur;
}

int main()
{
scanf("%d",&t);
while(t--){
scanf("%s",s + 1);
memset(p,0,sizeof p);
memset(r,0,sizeof r);
getS();
manachar();
for(int i = 0;i <= n; i++){
tree[i] = 0;
G[i].clear();
}
for(int i = 1;i <= n / 2; i++){
r[i] = p[i * 2] / 2;
G[i - r[i]].push_back(i);
}
LL ans = 0;
for(int i = 1;i <= n / 2; i++){
for(int j = 0;j < G[i - 1].size(); j++) update(G[i - 1][j]);
ans += sum(i + r[i] - 1) - sum(i);
}
printf("%lld\n",ans);
}
}

11-11 850

05-16 138
09-23 119