欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

P5496 【模板】回文自动机(PAM)

程序员文章站 2024-03-09 08:59:41
...

题目背景
模板题,无背景(其实是我想不出背景)。

题目描述
给定一个字符串 s。保证每个字符为小写字母。对于 s 的每个位置,请求出以该位置结尾的回文子串个数。

这个字符串被进行了加密,除了第一个字符,其他字符都需要通过上一个位置的答案来解密。

具体地,若第 ii(i≥1) 个位置的答案是 k,第 i+1 个字符读入时的 ASCII 码为 c,则第 i+1 个字符实际的 ASCII 码为 (c−97+k)mod26+97。所有字符在加密前后都为小写字母。

输入格式
一行一个字符串 s 表示被加密后的串。

输出格式
一行, ∣s∣ 个整数。第 i个整数表示原串以第 i个字符结尾的回文子串个数。

输入输出样例
输入 #1
debber
输出 #1
1 1 1 2 1 1
输入 #2
lwk
输出 #2
1 1 2
输入 #3
lxl
输出 #3复制
1 1 1
说明/提示
对于 100% 的数据, 1≤∣s∣≤5×10^5

理解了PAM,这题真的很简单了
代码:

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#define maxx 500005
#define N 26
using namespace std;
typedef long long ll;
int ans[maxx],tot;
struct PAM
{
    int nex[maxx][N];
    int fail[maxx];
    int cnt[maxx];
    int num[maxx];
    int len[maxx];
    int S[maxx];
    int last;
    int n;
    int p;

    inline int newNode(int l)//if single case
    {
        //for(int i=0;i<26;i++)nex[p][i]=0;
        //cnt[p]=0;
        //num[p]=0;
        len[p]=l;
        return p++;
    }
    void init()
    {

        p=0;
        newNode(0);newNode(-1);
        last=0;n=0;
        S[n]=-1;
        fail[0]=1;
    }
    inline int getFail(int x)
    {
        while(S[n-len[x]-1]!=S[n])x=fail[x];
        return x;
    }
    inline void insert(int c)
    {
        c-='a';
        S[++n]=c;
        int cur=getFail(last);
        if(!nex[cur][c])
        {
            int now=newNode(len[cur]+2);
            fail[now]=nex[getFail(fail[cur])][c];
            nex[cur][c]=now;
            num[now]=num[fail[now]]+1;

        }
        last=nex[cur][c];
        ans[tot++]=num[last];
        cnt[last]++;
    }
    void count()
    {
        for(int i=p;i>=0;i--)cnt[fail[i]]+=cnt[i];
    }
}pam;
char c[maxx];
int main()
{
    scanf("%s",c);
    pam.init();
    pam.insert(c[0]);
    for(int i=1;c[i];i++)
    {
        int _c=(c[i]-'a'+ans[i-1])%26+'a';
        pam.insert(_c);
    }
    printf("%d",ans[0]);
    for(int i=1;i<tot;i++)printf(" %d",ans[i]);
    printf("\n");
    return 0;
}