分析:
- 首先考虑遍历所有的两头的
i,k
,然后去找他们中间的一个点
c
,让这个点把
str[i...k] 且成两段回文串。
这样是可行的,但是复杂度枚举两头已经是 O(n2) 了。 - 然后考虑换一个思路,枚举所有的中间的隔代
c
,然后以
c 为隔代的满足条件的所有回文串的两头。
这样发现,用所有以 c 左边元素为结尾的回文串的左边界和乘以以c 右边元素为开始的所有回文串的右边界和,就是 c 为隔代的贡献。
我们要
扫描线可以带权的。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define pr(x) cout << #x << ": " << x << " "
#define pl(x) cout << #x << ": " << x << endl;
struct jibancanyang
{
static const int maxn = int(2e6) +7, mod = int(1e9) + 7;
char str[maxn], aim[maxn * 2];
int ti, len, P[maxn * 2];
long long cntl[maxn], suml[maxn], cntr[maxn], sumr[maxn];
long long ans;
void pre() {
len = strlen(str);
ti = 0;
aim[ti++] = '^';
for (int i = 0; i < len; ++i) aim[ti++] = '#', aim[ti++] = str[i];
aim[ti++] = '#', aim[ti++] = '$';
}
void aft() {
memset(suml, 0, sizeof(suml));
memset(sumr, 0, sizeof(suml));
memset(cntl, 0, sizeof(suml));
memset(cntr, 0, sizeof(suml));
for (int i = 2; i < ti - 2; ++i) {
int c = i;
int l, r;
l = i - (P[i] - 1), r = i + (P[i] - 1);
cntl[c + 1]++, cntl[r + 2]--;
cntr[c - 1]++, cntr[l - 2]--;
suml[c + 1] += i, suml[r + 2] -= i;
sumr[c - 1] += i, sumr[l - 2] -= i;
}
long long sx = 0, sm = 0;
for (int i = 0; i < ti; ++i) {
sx += cntl[i];
sm += suml[i];
if (i % 2 && i > 2 && i < ti - 3) {
suml[i] = ((sm - (i - 1 ) / 2 * sx) + mod) % mod;
}
}
sx = 0, sm = 0;
for (int i = ti - 1; i >= 0; --i) {
sx += cntr[i];
sm += sumr[i];
if (i % 2 && i > 2 && i < ti - 3) {
sumr[i] = ((sm - (i + 1) / 2 * sx) + mod) % mod;
}
}
ans = 0;
for (int i = 3; i < ti - 3; i += 2) {
ans = ans + suml[i] * sumr[i] ;
ans %= mod;
}
}
void manacher() {
pre();
memset(P, 0, sizeof(P));
int C = 0, R = 0;
for (int i = 1; i < ti - 1; ++i) {
int i_mirror = 2 * C - i;
P[i] = (R > i) ? min((R - i), P[i_mirror]) : 0;
while (aim[i + 1 + P[i]] == aim[i - 1 - P[i]]) ++P[i];
if (i + P[i] > R) C = i, R = i + P[i];
}
aft();
}
void fun() {
while (~scanf("%s", str)) manacher(), printf("%lld\n", ans);
}
}ac;
int main()
{
#ifdef LOCAL
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif
ac.fun();
return 0;
}