URAL 2060 Subpalindrome Pairs Manacher

来源:互联网 发布:ubuntu 默认文件系统 编辑:程序博客网 时间:2024/06/05 10:41

给一个长度为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+pj1ijpj+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

0 0