一眼可得PAM

如果没学过PAM的可以看这里:PAM学习小结

我们令PAM上多记录一个信息\(sum\),表示该节点表示串在原串上出现了多少次。

当我们处理完了\(sum\),对于长度\(len\)为奇数的节点的信息\(sum\)计入数组\(a[i]\).

\(a[i]\)为长度为\(i\)的回文子串出现次数。

\(a[i]\)降序排序后累加答案快速幂处理一下即可,不需太多点拨

重点来了

讲一下怎么处理\(sum\)

我们可以发现当一个节点\(u\)的\(sum+1\),那么\(fail[u]\)的\(sum\)也要\(+1\)

熟悉AC自动机的OIer可以敏锐的察觉到可以用拓扑排序了(例如我

PAM的时候打个标记,最后统一一个拓扑排序向\(fail\)去更新\(sum\)即可

queue<int >q;		//in数组为fail入边数量
void tuopu(){
for(int i=0;i<=tot;i++)if(in[i]==0)q.push(i);
while(!q.empty()){
int u=q.front();q.pop();
sum[fail[u]]+=sum[u];in[fail[u]]--;
if(in[fail[u]]==0)q.push(fail[u]);
}
}

好像没什么问题,多一个拓扑排序就行了

但真的如此吗?

我们观察PAMAC自动机的区别

AC自动机是建好\(Trie\)后再进行\(getFail\)的,\(fail\)的节点编号是会大于自身节点编号

PAM不会出现这种情况,PAM\(fail\)定义不同于AC自动机,构建使用增量法,保证了\(fail\)的节点编号一定小于自身节点编号。

所以就可以不用拓扑排序了,直接一个\(for\)从后到前更新即可

for(int i=tot;i>=0;i--)sum[fail[i]]+=sum[i];

总代码:

#include<bits/stdc++.h>
#define maxn 1010001
#define ll long long
#define mod 19930726
using namespace std;
char s[maxn];
int fail[maxn],len[maxn],trie[maxn][26],trans[maxn];
long long sum[maxn];
int per,slen,tot;
long long a[maxn],K,ans=1;
int getfail(int x,int i){
while(i-len[x]-1<0||s[i-len[x]-1]!=s[i])x=fail[x];
return x;
}
int gettrans(int x,int i){
while(((len[x]+2)<<1)>len[tot]||s[i-len[x]-1]!=s[i])x=fail[x];
return x;
}
void insert(int u,int i){
int Fail=getfail(per,i);
if(!trie[Fail][u]){
len[++tot]=len[Fail]+2;
fail[tot]=trie[getfail(fail[Fail],i)][u];
trie[Fail][u]=tot;
if(len[tot]<=2)trans[tot]=fail[tot];
else{
int Trans=gettrans(trans[Fail],i);
trans[tot]=trie[Trans][u];
}
}
per=trie[Fail][u];
sum[per]++; //记录sum
}
ll qpow(ll n,ll m){
ll ans=1ll;
while(m){
if(m&1){ans=ans*n;ans%=mod;}
n=n*n;n%=mod;m>>=1;
}return ans%mod;
}
int main(){
scanf("%d%lld",&slen,&K);
scanf("%s",s);
fail[0]=1;len[1]=-1;tot=1;
for(int i=0;i<slen;i++)insert(s[i]-'a',i);
for(int i=tot;i>=1;i--)sum[fail[i]]+=sum[i]; //更新sum
for(int i=2;i<=tot;i++)a[len[i]]+=sum[i],a[len[i]]%=mod; //长度处理
for(int i=slen;i>=1;i--){ //答案处理
if(i%2==1){
if(K>=a[i]){
ans*=qpow(i,a[i]);ans%=mod;
K-=a[i];
}else{
ans*=qpow(i,K);ans%=mod;
K-=K;
break;
}
}
}
if(K==0) //判-1
printf("%lld\n",ans%mod);
else
printf("-1\n");
return 0;
}

题解 P1659 【[国家集训队]拉拉队排练】的更多相关文章

  1. luogu P1659 [国家集训队]拉拉队排练

    唔....话说好久没有发布题解了(手痒痒了 首先特别鸣谢lykkk大佬今天下午教我Manacher算法,甚是感谢 为了体现学习成果,写一篇蒟蒻版的题解(大佬勿喷 言归正传 题面——>在这儿 首先 ...

  2. 洛谷 P1659 [国家集训队]拉拉队排练(Manacher)

    题目链接:https://www.luogu.com.cn/problem/P1659 思路: 首先跑一遍Manacher,用$cnt_i$记录长为$i$的回文串有多少个. 所记录的$cnt$并不是最 ...

  3. P1659 [国家集训队]拉拉队排练

    思路 求出cnt和len之后,直接乘起来即可 代码 #include <cstdio> #include <algorithm> #include <cstring> ...

  4. Manacher【p1659】 [国家集训队]拉拉队排练

    题目描述 n个女生举牌子(只含有26个小写字母,长度为n的字符串), 如果连续的一段女生,有奇数个,并且她们手中的牌子所写的字母,从左到右和从右到左读起来一样,那么这一段女生就被称作和谐小群体. 现在 ...

  5. 【洛谷 P1659】 [国家集训队]拉拉队排练(manacher)

    题目链接 马拉车+简单膜你 #include <cstdio> #include <cstring> #include <algorithm> using name ...

  6. [回文树][BZOJ2160][国家集训队]拉拉队排练

    题面 Description 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助篮 ...

  7. [国家集训队]拉拉队排练 Manancher_前缀和_快速幂

    Code: #include <cstdio> #include <algorithm> #include <cstring> using namespace st ...

  8. [国家集训队] 拉拉队排练 - Manacher

    用 Manacher 跑出回文串长,注意这里不需要偶数长度所以不需要对串做一些奇怪的处理 然后用前缀和搞一下,计算答案时跑快速幂即可 #include <bits/stdc++.h> us ...

  9. 【题解】国家集训队礼物(Lucas定理)

    [国家集训队]礼物(扩展Lucas定理) 传送门可以直接戳标题 172.40.23.20 24 .1 答案就是一个式子: \[ {n\choose \Sigma_{i=1}^m w}\times\pr ...

随机推荐

  1. Linq to SQL各种参考

    原文:https://www.cnblogs.com/lyj/archive/2008/01/23/1049686.htmlhttps://www.cnblogs.com/lyj/archive/20 ...

  2. 使用Maven导入MySQL驱动包遇到的问题

    问题描述 今天在使用Maven导入MySQL数据库驱动包依赖后,直接运行项目,出现错误. java.sql.SQLException: No suitable driver found for jdb ...

  3. 利用ICMP协议的PING命令获取客户端当前网络质量 by徐文棋

    无论在windows下,linux也好,unix也好,都可以通过 Ping命令获得当前设备的网络延迟,延迟是客户端到服务端的网络响应时间.通常延迟越低,反应速度越快 这里使用了SimplePing   ...

  4. Docker安全及日志管理

    Docker安全及日志管理 目录 Docker安全及日志管理 一.Docker容器与虚拟机的区别 1. 隔离与共享 2. 性能与损耗 3. 总结 二.Docker存在的安全问题 1. Docker自身 ...

  5. LVS+Keepalived群集

    LVS+Keepalived群集 目录 LVS+Keepalived群集 一.Keepalived实现原理 1. 单服务器的风险 2. Keepalived工具 3. Keepalived解决单点故障 ...

  6. JS快速入门(二)

    目录 JS快速入门(二) 结构图 BOM window对象 open() window子对象 location对象 history对象(了解) navigator 对象 screen对象 BOM 定时 ...

  7. MySQL高性能学习笔记

    索引 何为索引?有什么作用? 索引是一种用于快速查询和检索数据的数据结构.常见的索引结构有: B 树, B+树和 Hash. 索引的作用就相当于目录的作用.打个比方: 我们在查字典的时候,如果没有目录 ...

  8. Solution -「洛谷 P6021」洪水

    \(\mathcal{Description}\)   Link.   给定一棵 \(n\) 个点的带点权树,删除 \(u\) 点的代价是该点点权 \(a_u\).\(m\) 次操作: 修改单点点权. ...

  9. Large Sacle Distributed Deep Networks

    本文是谷歌发表在NeurIPS 2012上的一篇论文,主要讨论了在几万个CPU节点上训练大规模深度网络的问题,并提出了一个名为DistBelief的软件框架.在该框架下实现了两种大规模分布式训练算法: ...

  10. MXNet源码分析 | Gluon接口分布式训练流程

    本文主要基于MXNet1.6.0版本,对Gluon接口的分布式训练过程进行简要分析. 众所周知,KVStore负责MXNet分布式训练过程中参数的同步,那么它究竟是如何应用在训练中的呢?下面我们将从G ...