回文自动机

模板题:https://www.luogu.org/problemnew/show/P3649

知识点:1.回文自动机算法,关键在于理解getfail函数和fail数组(与AC自动机有些相似)

    2.初始化。

    3.注意cnt的定义,就比如说此题中每个回文串的出现次数不只是cnt[i]。

#include <bits/stdc++.h>
using namespace std;
char c[1300002];
long long lst,tot;
long long ch[300002][30],cnt[300002],len[300002],fail[300002];
void init()
{
    len[0] = 0,len[1] = -1;
    fail[0] = 1;
    tot = 1;
    lst = 0;
    c[0] = '~';
}
long long getfail(long long t,long long x)
{
    while(c[t - len[x] - 1] != c[t])x = fail[x];
    return x;
}
long long newnode(long long t)
{
    len[++tot] = t;
    return tot;
}
void insert(long long t)
{
    long long x;
    x = getfail(t,lst);
    long long u = c[t] - 'a';
    if(!ch[x][u])
    {
        long long h = newnode(len[x] + 2);
        fail[h] = ch[getfail(t,fail[x])][u];//wrong1:AC:ch[getfail(fail[x],t)][u],WA:ch[getfail(t,fail[x])][u]
        ch[x][u] = h;
    }
    ++cnt[ch[x][u]];
    lst = ch[x][u];
}
void count()
{
    for(long long i = tot;i > 0;i--)
    cnt[fail[i]] += cnt[i];
}
int main()
{
    scanf("%s",c + 1);
    init();
    long long length = strlen(c + 1);
    for(long long i = 1;i <= length;i++)
    {
        insert(i);
    }
    count();
    long long ans = -1;
    for(long long i = tot;i >= 0;i--)
    {
        ans = max(ans,cnt[i] * len[i]);
    }
    printf("%lld",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/xyj1/p/10620832.html