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

题目描述

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

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

具体地,若第 i ( i ≥ 1 ) i(i\geq 1) i(i1) 个位置的答案是 k k k,第 i + 1 i+1 i+1 个字符读入时的 A S C I I ASCII ASCII 码为 c c c,则第 i + 1 i+1 i+1 个字符实际的 A S C I I ASCII ASCII 码为 ( c − 97 + k )   m o d   26 + 97 (c-97+k)\bmod 26+97 (c97+k)mod26+97。所有字符在加密前后都为小写字母。

输入格式

一行一个字符串 s s s 表示被加密后的串。

输出格式

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

回文树模板题,只是强制在线,需要用到前面的回文串的个数k

#include<bits/stdc++.h>
using namespace std;
const int MAXNODE = 6e5+50;
const int MOD = 1e9+7;
struct Palindrome{
    int nxt[MAXNODE][26],fail[MAXNODE],len[MAXNODE],cnt[MAXNODE];
    int sz,last,sn;
    char s[MAXNODE];
    Palindrome(){
        len[0]=0,len[1]=-1;
        fail[0]=1,fail[1]=0;
        last = sn = 0,sz = 1;
        s[0] = '#';//将第一个字符表示成字符串中没出现过的字符
    }
    int Build(char ch){
        s[++sn] = ch;
        int root = last;
        while(s[sn-len[root]-1]!=ch)
            root = fail[root];
        if(!nxt[root][ch-'a']){
            len[++sz] = len[root] + 2;
            int tmp = fail[root];
            while(s[sn-len[tmp]-1]!=ch)
                tmp = fail[tmp];
            fail[sz] = nxt[tmp][ch-'a'];
            cnt[sz] = cnt[fail[sz]] + 1;
            nxt[root][ch-'a'] = sz;
        }
        last = nxt[root][ch-'a'];
        return cnt[last];
    }
}PAM;
char str[MAXNODE];
int main(){
    scanf("%s",str);
    int len = strlen(str);
    for(int i=0,k=0;i<len;i++){
        str[i] = (str[i]-97+k)%26+97;
        k = PAM.Build(str[i]);
        printf("%d ",k);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值