首先我们正着对每一个 (j) 求一边 (displaystyle sum i),设为 (a[j])
类似的倒着对每个 (j) 求一边 (displaystyle sum k),设为 (b[j])
那么答案就是 (displaystyle sum a[i] imes b[i+1])
考虑如何求 (a) 我们在建立回文自动机的时候统计一下以 (j) 为结尾的回文串的个数 (num) 以及回文串的长度和 (sum), 则 (a[j]=(i+1) imes num -sum)
倒着也同理
#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
int T, n;
LL ans;
const int N = 1000010, mod = 1e9 + 7;
int a[N], b[N];
char s[N];
struct PAM
{
int em, last, cnt, now;
int tr[N][26], len[N], fail[N], sum[N], num[N];
void YYCH()
{
for (int i = 0; i <= cnt; ++i)
{
len[i] = num[i] = fail[i] = sum[i] = 0;
for (int j = 0; j < 26; ++j)tr[i][j] = 0;
}
fail[0] = 1; fail[1] = 0; len[0] = 0; len[1] = -1; cnt = 1; last = 0;
}
int getfail(int x)
{
if (now == 1)while (s[em - len[x] - 1] != s[em])x = fail[x];
else while (s[em + len[x] + 1] != s[em])x = fail[x];
return x;
}
void Insert(int x)
{
int f1 = getfail(last);
if (!tr[f1][x])
{
len[++cnt] = len[f1] + 2;
fail[cnt] = tr[getfail(fail[f1])][x];
num[cnt] = num[fail[cnt]] + 1;
sum[cnt] = sum[fail[cnt]] + len[cnt]; sum[cnt] %= mod;
tr[f1][x] = cnt;
}
last = tr[f1][x];
}
} P;
int main()
{
freopen("triple.in", "r", stdin);
freopen("triple.out", "w", stdout);
cin >> T;
while (T--)
{
scanf("%s", s + 1); n = strlen(s + 1); ans = 0;
P.YYCH(); P.now = 1;
for (int i = 1; i <= n; ++i)
{
P.em = i; P.Insert(s[i] - 'a');
a[i] = ((LL)(i + 1) * P.num[P.last] - P.sum[P.last]) % mod;
}
P.YYCH(); P.now = 2;
for (int i = n; i >= 1; --i)
{
P.em = i; P.Insert(s[i] - 'a');
b[i] = ((LL)(i - 1) * P.num[P.last] + P.sum[P.last]) % mod;
}
for (int i = 1; i < n; ++i)(ans += (LL)a[i] * b[i + 1]) %= mod;
cout << (ans % mod + mod) % mod << '
';
}
fclose(stdin); fclose(stdout);
return 0;
}