P5496 【模板】回文自动机(PAM)
程序员文章站
2024-03-09 08:59:35
...
题目描述
给定一个字符串 。保证每个字符为小写字母。对于 ss 的每个位置,请求出以该位置结尾的回文子串个数。
这个字符串被进行了加密,除了第一个字符,其他字符都需要通过上一个位置的答案来解密。
具体地,若第 个位置的答案是 ,第 个字符读入时的 码为 ,则第 个字符实际的 码为 。所有字符在加密前后都为小写字母。
输入格式
一行一个字符串 表示被加密后的串。
输出格式
一行, 个整数。第 个整数表示原串以第 个字符结尾的回文子串个数。
回文树模板题,只是强制在线,需要用到前面的回文串的个数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;
}