题意:相邻的两端回文串的价值为两个回文串总的区间左端点 × 区间右端点。然后计算目标串中所有该情况的总和。
思路:首先用manacher求出所有中心点的最大半径,然后我们知道对于左区间我们把贡献记录在右端点,右区间记录在左端点。然后细节的我就不太懂了。迷~
#include<bits/stdc++.h>
using namespace std; const int maxn = 2e6 +;
const int mod = 1e9 + ;
long long rad[maxn], L[maxn], R[maxn], cnt1[maxn], cnt2[maxn];
char in[maxn], str[maxn]; void manacher(){
int len = strlen(in), l = ;
str[l ++] = '$'; str[l ++] = '#';
for(int i = ; i < len; i ++)
str[l ++] = in[i], str[l ++] = '#';
str[l] = ;
int mx = , id = ;
for(int i = ; i < l; i ++) {
rad[i] = mx > i ? min(rad[ * id - i], 1LL * mx - i) : ;
while(str[i + rad[i]] == str[i - rad[i]]) rad[i] ++;
if(i + rad[i] > mx){
mx = i + rad[i];
id = i;
}
}
} int main(){ while(~scanf("%s", in)) {
int len = strlen(in);
manacher();
// for(int i = 0; i < 2 * len + 2; i ++) printf(" %d ", rad[i]);
memset(cnt1, , sizeof(cnt1));
memset(cnt2, , sizeof(cnt2));
for(int i = ; i <= * len; i ++){
cnt1[i - rad[i] + ] += i; cnt1[i + ] -= i;
cnt2[i - rad[i] + ] ++; cnt2[i + ] --;
}
for(int i = ; i <= * len; i ++){
cnt1[i] += cnt1[i - ], cnt2[i] += cnt2[i - ];
if(i % == ) R[i/] = (cnt1[i] - i / * cnt2[i]) % mod;
}
memset(cnt1, , sizeof(cnt1));
memset(cnt2, , sizeof(cnt2));
for(int i = ; i <= * len; i ++) {
cnt1[i + rad[i]] -= i; cnt1[i] += i;
cnt2[i + rad[i]] --; cnt2[i] ++;
}
for(int i = ; i <= * len; i ++) {
cnt1[i] += cnt1[i - ]; cnt2[i] += cnt2[i - ];
if(i % == ) L[i / ] = (cnt1[i] - i / * cnt2[i]) % mod;
}
long long ans = ;
for(int i = ; i < len; i ++) ans = (ans + L[i] * R[i + ] % mod) % mod;
printf("%lld\n", ans);
}
return ;
}