URAL 2060 Subpalindrome Pairs Manacher

给一个长度为n的字符串,找三元组(i,j,k)的个数满足s[i..j]是一个回文串,s[j+1..k]是一个回文串。( ij<k ).

样例的abaa的三元组有
(1,1,2)
(1,3,4)
(2,2,3)
(2,3,4)
(3,3,4)

和SHOI的那个双倍回文差不多。
找出所有的极长回文子串后,指针i正反扫2次,统计满足 j+pj1i jpj+1i 的j的个数,因为i是单调增/减的,所以左边那块可以用set维护。

没开long long WA了一发。。

#include <cstdio>
#include <cstring>
#include <set>
using namespace std;
const int N = 610000;
char s[N]; int p[N], a[N], c[N], d[N];
multiset<int> S;
int main() {
    int i, n, m, mx = 0, id;
    long long ans = 0;
    scanf("%s", s + 1);
    n = strlen(s + 1); m = 2 * n + 1;
    for (i = 1; i <= n; ++i) {
        a[i * 2] = s[i];
        a[i * 2 + 1] = '$';
    }
    a[0] = '+'; a[m + 1] = '-'; a[1] = '$';
    for (i = 1; i <= m; ++i) {
        if (mx > i) p[i] = min(mx - i, p[2 * id - i]);
        else p[i] = 1;
        for (; a[i - p[i]] == a[i + p[i]]; ++p[i]);
        if (i + p[i] > mx) mx = i + p[i], id = i;
    }
    set<int>::iterator it;
    for (i = 1; i <= m; ++i) {
        S.insert(i + p[i] - 1);
        while (*(it = S.begin()) < i)
            S.erase(it);
        c[i] = S.size();
    }
    S.clear();
    for (i = m; i; --i) {
        S.insert(i - p[i] + 1);
        while (*(--(it = S.end())) > i) S.erase(it);
        d[i] = S.size();
    }
    for (i = 2; i < m; i += 2) ans += 1ll * c[i] * d[i + 2];
    printf("%lld", ans);
    return 0;
}

2060. Subpalindrome pairs

Your task is to calculate number of triplets (i, j, k) such that i ≤ j < k and s[i..j] is a palindrome and s[j+1 .. k] is a palindrome.

Input

The input contains a line of n lowercase Latin letters (1 ≤ n ≤ 3 · 105).

Output

Output the answer.

Sample

input

abaa

output

5

你可能感兴趣的:(字符串,OI,Manacher,回文串,Timus)