此后如竟没有炬火 我便是唯一的光|

Day_Dreamer_D

园龄:3年6个月粉丝:3关注:16

2022-04-11 15:12阅读: 38评论: 1推荐: 0

CF 835D Palindromic characteristics 题解

做法一:字符串哈希

暴力枚举子串,Hash 判断两边是否可行,时间复杂度 O(n2logn)

做法二:DP

这篇文章 写的很清楚。

做法三:PAM

当数据范围 1|s|5000000 时,前两种方法是过不去的,能过去也可以被 Hack。所以我们考虑线性的做法,而 PAM 在插入之后上传 fail 树,使 cnt 数组可以 O(n) 求出。

gp 表示长度小于 lenp2 的最长回文后缀,fp 表示回文串 p 的阶数,易得以下结论:

{fp=1 if lenp2lengpfp=fgp+1 otherwise 

统计答案时,枚举 p,令 ansfp+=cntp,最终答案就是对 ans 数组求出后缀和。

namespace LZX
{
using namespace std;
const int MAXN=5000005;
int s[MAXN],n,ch[MAXN][26],idx,fail[MAXN],last,len[MAXN],cnt[MAXN],g[MAXN],f[MAXN];
long long ans[MAXN];
char str[MAXN];
int s_PAM_newnode(int l)
{
len[++idx]=l;
return idx;
}
void s_PAM_clear()
{
idx=-1;
n=last=0;
s_PAM_newnode(0);
s_PAM_newnode(-1);
fail[0]=1;
s[0]=-1;
return;
}
int s_PAM_getfail(int p)
{
while(s[n]^s[n-len[p]-1])
{
p=fail[p];
}
return p;
}
void s_PAM_insert(int awa)
{
int p,c,now;
s[++n]=awa;
p=s_PAM_getfail(last);
if(!ch[p][awa])
{
c=s_PAM_newnode(len[p]+2);
fail[c]=ch[s_PAM_getfail(fail[p])][awa];
if(len[c]<=2)
{
g[c]=fail[c];
}
else
{
now=g[p];
while(s[n]^s[n-len[now]-1]||(len[now]+2)*2>len[c])
{
now=fail[now];
}
g[c]=ch[now][awa];
}
ch[p][awa]=c;
}
last=ch[p][awa];
cnt[last]++;
return;
}
int _main()
{
int l;
scanf("%s",str);
l=strlen(str);
s_PAM_clear();
for(int i=0;i<l;i++)
{
s_PAM_insert(str[i]-'a');
}
for(int i=idx;i>=2;i--)
{
cnt[fail[i]]+=cnt[i];
}
for(int i=2;i<=idx;i++)
{
if(len[i]/2==len[g[i]])
{
f[i]=f[g[i]]+1;
}
else
{
f[i]=1;
}
ans[f[i]]+=1ll*cnt[i];
}
for(int i=l;i;i--)
{
ans[i]+=ans[i+1];
}
for(int i=1;i<=l;i++)
{
printf("%lld ",ans[i]);
}
printf("\n");
return 0;
}
}

 

本文作者:Day_Dreamer_D

本文链接:https://www.cnblogs.com/2020gyk080/p/16130111.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Day_Dreamer_D  阅读(38)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起