回文树/回文自动机(Palindrome Tree / Palindrome Automaton)

该实现的常数很大。

#include <cstdio>
#include <cstring>
#include <algorithm>

const int MAXN = 300005;
const int CHAR_SET = 26;

struct PalinT {
    struct Node {
        Node *c[CHAR_SET], *fail;
        int len, cnt;

        Node(int len = 0) : len(len), cnt(0), c(), fail(NULL) {}
    } *even, *odd, *last, _pool[MAXN], *_curr;
    char str[MAXN];
    int size;

    PalinT() : str() {
        _curr = _pool;
        last = even = new (_curr++) Node;
        even->fail = odd = new (_curr++) Node(-1);
        odd->fail = odd;
        str[size = 0] = -1;
    }

    Node *extend(int c) {
        str[++size] = c;
        Node *v = last;
        for (; str[size - v->len - 1] != str[size]; v = v->fail) {}

        Node *u = v->c[c];
        if (!u) {
            u = v->c[c] = new (_curr++) Node(v->len + 2);
            Node *p = v->fail;
            for (; str[size - p->len - 1] != str[size]; p = p->fail) {}
            u->fail = v == odd ? even : p->c[c];
        }
        u->cnt++;

        return last = u;
    }

    void build(char *begin, char *end) {
        for (char *p = begin; p != end; p++) extend(*p - 'a');
    }

    void count() {
        for (Node *p = _curr - 1; p >= _pool; p--) p->fail->cnt += p->cnt;
    }
} palinT;

int main() {
    static char s[MAXN];
    scanf("%s", s);

    int n = strlen(s);
    palinT.build(s, s + n);
    palinT.count();

    long long ans = 0;
    for (PalinT::Node *p = palinT._pool; p != palinT._curr; p++)
        ans = std::max(ans, (long long) p->len * p->cnt);

    printf("%lld\n", ans);

    return 0;
}

results matching ""

    No results matching ""