APIO 2014 回文串(Manacher+后缀自动机+倍增)
题意
https://www.lydsy.com/JudgeOnline/problem.php?id=3676
思路
好像还是回文自动机裸体,但是 \(\text{Manacher}\) +后缀自动机+倍增也可以解决。
首先可以一遍 \(\text{Manacher}\) 得到本质不同的回文串,然后分别求一次出现次数,更新答案。不能发现后缀自动机可以比较轻松的求出一个字串的出现次数,但是需要快速回答。所以需要快速找到一个字串在后缀自动机上的所属节点。
注意到后缀链接连接着一段后缀相等的位置,所以预处理 \([1,i]\) 在后缀自动机的位置,对于一个串 \([s,t]\) ,从 \([1,t]\) 的位置开始跳后缀链接,找到属于 \([s,t]\) 的位置,这里使用倍增跳跃就可以做到一个 \(\log\) 。
有一个细节,空间开不下的话,后缀数组的 \(ch\) 用完了之后可以拿来跳倍增。
代码
#include<bits/stdc++.h>
#define FOR(i,x,y) for(int i=(x),i##END=(y);i<=i##END;++i)
#define DOR(i,x,y) for(int i=(x),i##END=(y);i>=i##END;--i)
template<typename T,typename _T>inline bool chk_min(T &x,const _T y){return y<x?x=y,1:0;}
template<typename T,typename _T>inline bool chk_max(T &x,const _T y){return x<y?x=y,1:0;}
typedef long long ll;
const int N=(int)6e5+5;
template<const int maxn,const int maxm,typename T>struct Linked_list
{int head[maxn],nxt[maxm],tot;T to[maxm];Linked_list(){clear();}T &operator [](const int x){return to[x];}void clear(){memset(head,-1,sizeof(head)),tot=0;}void add(int u,T v){to[++tot]=v,nxt[tot]=head[u],head[u]=tot;}#define EOR(i,G,u) for(int i=G.head[u];~i;i=G.nxt[i])
};
Linked_list<N,N,int>G;
int ch[N][26],slink[N],len[N],sz[N];
int *fa[N];
int las,tot;
char str[N];int idx[N];
char mnc[N];int p[N];
int n;
ll ans;void init()
{las=tot=1;FOR(i,0,25)ch[1][i]=0;len[1]=slink[1]=0;
}
void extend(char c)
{int p=las,cur=++tot;FOR(i,0,25)ch[cur][i]=0;len[cur]=len[p]+1;sz[cur]=1;for(;p&&!ch[p][c-'a'];p=slink[p])ch[p][c-'a']=cur;if(!p)slink[cur]=1;else{int q=ch[p][c-'a'];if(len[p]+1==len[q])slink[cur]=q;else{int clone=++tot;FOR(i,0,25)ch[clone][i]=ch[q][i];slink[clone]=slink[q];len[clone]=len[p]+1;sz[clone]=0;slink[cur]=slink[q]=clone;for(;p&&ch[p][c-'a']==q;p=slink[p])ch[p][c-'a']=clone;}}las=cur;
}
void dfs(int u)
{EOR(i,G,u){int v=G[i];dfs(v);sz[u]+=sz[v];}
}void solve(int l,int r)
{int p=idx[r];DOR(i,20,0)if(len[fa[p][i]]>=r-l+1)p=fa[p][i];chk_max(ans,1ll*sz[p]*(r-l+1));
}void Manacher(char *str,int len)
{int n=1;mnc[1]='#';FOR(i,1,len)mnc[++n]=str[i],mnc[++n]='#';int mr=0,pos;FOR(i,1,n){if(i<=mr)p[i]=std::min(p[(pos<<1)-i],mr-i+1);else p[i]=1;while(i-p[i]>=1&&i+p[i]<=n&&mnc[i-p[i]]==mnc[i+p[i]]){p[i]++;if(mnc[i-p[i]+1]=='#')solve((i-p[i]+1+1)>>1,(i+p[i]-1-1)>>1);}if(chk_max(mr,i+p[i]-1))pos=i;}
}int main()
{scanf("%s",str+1);n=strlen(str+1);init();FOR(i,1,n)extend(str[i]),idx[i]=las;FOR(i,2,tot)G.add(slink[i],i);FOR(i,0,tot)fa[i]=ch[i];FOR(i,1,tot)fa[i][0]=slink[i];FOR(j,1,20)FOR(i,1,tot)fa[i][j]=fa[fa[i][j-1]][j-1];dfs(1);Manacher(str,n);printf("%lld\n",ans);return 0;
}
转载于:https://www.cnblogs.com/Paulliant/p/10777555.html
APIO 2014 回文串(Manacher+后缀自动机+倍增)相关推荐
- 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)
传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...
- [国家集训队]最长双回文串 manacher
---题面--- 题解: 首先有一个直观的想法,如果我们可以求出对于位置i的最长后缀回文串和最长前缀回文串,那么我们枚举分界点然后合并前缀和后缀不就可以得到答案了么? 所以我们的目标就是求出这两个数列 ...
- bzoj 2565: 最长双回文串 manacher算法
2565: 最长双回文串 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem. ...
- 洛谷P4555 [国家集训队]最长双回文串(manacher 线段树)
题意 题目链接 Sol 我的做法比较naive..首先manacher预处理出以每个位置为中心的回文串的长度.然后枚举一个中间位置,现在要考虑的就是能覆盖到i - 1的回文串中 中心最靠左的,和能覆盖 ...
- BZOJ 2565 最长双回文串 Manacher
题目大意: 定义双回文串G是指一个可以被拆分成两个部分(S和T)的字符串G = S + T, 且S和T都是回文串的串, G自己本身可以不是回文串 给出一个长度为n ( 2 <= n <= ...
- 【BZOJ2565】最长双回文串 Manacher
题解: 首先我们写一个Manacher模板.. 然后我们可以把所有回文串的信息映射到左端点上, 每个点依此维护最长右连接回文串. 然后再顺着扫一遍就出解了. 代码: #include <cstd ...
- bzoj4755: [Jsoi2016]扭动的回文串 manacher+二分+Hash
bzoj4755: [Jsoi2016]扭动的回文串 Description JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的子串 ...
- 洛谷 P4324 [JSOI2016]扭动的回文串 manacher+字符串hash
题目描述 JYY有两个长度均为 NNN 的字符串 AAA 和 BBB. 一个扭动字符串 S(i,j,k)S(i,j,k)S(i,j,k) 由 AAA 中的第 iii 个字符到第 jjj 个字符组成的子 ...
- 牛客 - 小A的回文串(Manacher模板题)
题目链接:点击查看 题目大意:给出一个字符串s,现在可以对字符串进行一次操作,具体规则是可以将字符串的一个前缀在不改变顺序的情况下变为其后缀,问如何操作可以使得最长回文子串的长度尽可能长,题目要求输出 ...
最新文章
- 使用内存盘 格式化文件系统以及部署ceph-osd
- 007-SDK框架之LYWSDKInterfaceProtocol.cpp
- 贪心+构造 Codeforces Round #277 (Div. 2) C. Palindrome Transformation
- codeforces 765 E Tree Folding
- Facebook推出人脸识别新功能,防止用户肖像遭滥用
- java控制图片移动_多线程控制图片移动
- oracle安装出现getproces,oracle安装问题
- linux中的dup和fcntl的用法
- vue router-link 添加点击事件
- photoshop案例_玩手机不如学PS!200集入门到精通Photoshop自学教程分享3
- iOS ReactiveCocoa 最全常用API整理(可做为手册查询)
- 信息学奥赛C++语言:判断奇偶
- PHPExcel+phalcon+yii批量导入
- 开售破发、二手市场跳水 iPhone SE3 “割韭菜”功力大减
- 81页智慧城市-大数据决策与支撑平台解决方案
- Ubuntu安装OpenCV4记录
- ROS学习之error解决记录
- 2014中国飞思卡尔技术论坛即将开幕
- linux .trash,linux下trash代替rm
- 微信小程(JAVAScript)实现自定义柱状图
热门文章
- GROUPING amp; GROUPING_ID amp; GROUP_ID amp; GROUPING SETS
- 俄罗斯电力公司T Plus完成25MW光伏电站
- shell统计游戏活跃用户数之改进过程分析
- 7-34 通讯录的录入与显示 (10 分)
- Postman系列之发送不同HTTP类型请求
- ubuntu18.04 安装Teamviewer15出现依赖库出错
- 解决Keras 与 Tensorflow 版本之间的兼容性问题,导入keras报错:module 'tensorflow.python.keras.backend' has no attribute
- TokenInsight:反映区块链行业整体表现的TI指数较昨日同期下降3.29%
- Filecoin网络目前总质押量约为2930万枚FIL
- SAP License:SAP 期待CO新帐 VS FI新总帐