[加强版] Codeforces 835D Palindromic characteristics (回文自动机DP)

Posted suncongbo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[加强版] Codeforces 835D Palindromic characteristics (回文自动机DP)相关的知识,希望对你有一定的参考价值。

题目链接: https://codeforces.com/contest/835/problem/D

题意: 一个回文串是\(1\)-回文的,如果一个回文串的左半部分和右半部分一样且都是\(k\)-回文串(右半部分是指长度为该串长度除以二下取整的后缀),则该串为\((k+1)\)回文串,满足该串是\(k\)回文串的最大\(k\)称作该串的回文级别。给定一个串\(s\), 对于每一个\(k=1,2,...,n\)求出该串中有多少个位置不同的\(k\)-回文串。\(n\le 5\times 10^6\). (除数据范围外与原题均相同)

题解: \(n^2\)的做法肯定是以子串为状态进行dp, 但是显然废状态太多了,只有回文串dp值非零,而一个串本质不同的回文串的个数是\(O(n)\)的。

所以,以本质不同的回文串作为状态进行dp. 本质不同的回文串一一对应回文自动机上的节点。设\(f[x]\)表示\(x\)节点代表回文串的回文级别。

然后转移方程显然: 若\(x\)不存在长度为\([\fracx2]\)(中括号表示下取整)的回文后缀,则\(dp[x]=1\), 否则\(dp[x]\)等于那个回文后缀的\(dp\)值+1.

dp完之后,我们求的是本质不同,但是题目要求求位置不同,所以还需要再统计一下每个点的子树大小。

时间复杂度\(O(n)\).

代码 (Codeforces 835D AC)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define llong long long
using namespace std;

const int N = 1e6+2;
const int LGN = 23;
const int S = 26;
int son[N+3][S+1];
int fail[N+3];
int len[N+3];
int sz[N+3];
int tsz[N+3];
char a[N+3];
int dp[N+3];
int bd[N+3];
int ord[N+3];
int buc[N+3];
llong ans[N+3];
int n,siz,lstpos;

void initPAM()

    siz = lstpos = 1; fail[0] = fail[1] = 1; len[1] = -1; len[0] = 0; bd[0] = 0; bd[1] = 1;


void insertchar(int id)

    int p = lstpos;
    while(a[id]!=a[id-len[p]-1]) p = fail[p];
    if(!son[p][a[id]])
    
        siz++; int u = siz,v = fail[p];
        while(a[id]!=a[id-len[v]-1]) v = fail[v];
        fail[u] = son[v][a[id]]; son[p][a[id]] = u; len[u] = len[p]+2;
        if(len[u]<=2) bd[u] = fail[u];
        else
        
            bd[u] = bd[p];
            while(a[id]!=a[id-len[bd[u]]-1] || (len[bd[u]]+2)*2>len[u])
            
                bd[u] = fail[bd[u]];
            
            bd[u] = son[bd[u]][a[id]];
        
        if(len[bd[u]]==(len[u]>>1)) dp[u] = max(0,dp[bd[u]])+1;
        else dp[u] = 1;
    
    sz[son[p][a[id]]]++;
    lstpos = son[p][a[id]];


int main()

    initPAM();
    scanf("%s",a+1); n = strlen(a+1);
    for(int i=1; i<=n; i++) a[i]-=96;
    for(int i=1; i<=n; i++) insertchar(i);
    for(int i=2; i<=siz; i++) buc[len[i]]++;
    for(int i=1; i<=n; i++) buc[i] += buc[i-1];
    for(int i=siz; i>=2; i--) ord[(buc[len[i]]--)+1] = i;
    ord[0] = 1; ord[1] = 0;
    for(int j=siz; j>=2; j--)
    
        int u = ord[j];
        sz[fail[u]] += sz[u];
    
    for(int j=2; j<=siz; j++)
    
        ans[dp[j]] += (llong)sz[j];
    
    for(int j=LGN-1; j>=1; j--) ans[j] += ans[j+1];
    for(int i=1; i<=n; i++) printf("%I64d\n",ans[i]);
    return 0;

以上是关于[加强版] Codeforces 835D Palindromic characteristics (回文自动机DP)的主要内容,如果未能解决你的问题,请参考以下文章

CF 835D Palindromic characteristics(DP)

CodeForces813E:Army Creation (主席树---上一题的加强版)

OCAC暑期比赛第三场 J题 袋鼠认妈妈(加强版) 题解

思维题,加强读题能力CodeForces - 705B

Army Creation CodeForces - 813E (水题)

Codeforces 986D Perfect Encoding FFT 分治 高精度