Description

考虑一个只包含小写拉丁字母的字符串 \(S\). 我们定义 \(S\) 的一个子串 \(T\) 的 “出现值” 为 \(T\)\(S\) 中的出现次数乘以 \(T\) 的长度. 请你求出 \(S\) 的所有回文子串中的最大出现值.

Input

输入只有一行, 为一个只包含小写字母的非空字符串 \(S\).

Output

输出一个整数, 为所查回文子串的最大出现值.

Sample Input

abacaba

Sample Output

7

Data Range

数据满足:\(1 \leq |S| \leq 300000\).

Explanation

这道题用回文串自动机做比较方便, 但是除了这道题似乎没有别的什么卵用.

当然也可以用 SAM+Manacher......

传送门:http://blog.csdn.net/u013368721/article/details/42100363

听说这个自动机是一个俄国人发明的:http://codeforces.com/blog/entry/13959

Source Code


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;
typedef long long lli;
const int maxn = 300100;

class PalindromeAutomaton
{
public:
    int n, ncnt, last;
    int ch[maxn][26], par[maxn], len[maxn];
    int size[maxn];
    char* str;
    void init(int n, char str[])
    {
        this->n = n;
        this->str = str;
        ncnt = 1;
        par[0] = par[1] = 1;
        len[1] = -1;
        return ;
    }

    void insert(int c, int l)
    {
        int p = last;
        while (str[l - len[p] - 1] != str[l])
            p = par[p];
        if (!ch[p][c]) {
            int now = ++ncnt,
                q = par[p];
            len[now] = len[p] + 2;
            while (str[l - len[q] - 1] != str[l])
                q = par[q];
            par[now] = ch[q][c];
            ch[p][c] = now;
        }
        last = ch[p][c];
        size[last] += 1;
        return ;
    }
    lli eval(void)
    {
        lli res = 0;
        for (int i = ncnt; i > 0; i--) {
            size[par[i]] += size[i];
            res = max(res, (lli)size[i] * len[i]);
        }
        return res;
    }
} pam;

int n;
char str[maxn];

int main(int argc, char** argv)
{
    scanf("%s", str + 1);
    n = strlen(str + 1);
    pam.init(n, str);
    for (int i = 1; i <= n; i++)
        pam.insert(str[i] - 'a', i);
    lli res = pam.eval();
    printf("%lld\n", res);
    return 0;
}