BZOJ3676: [Apio2014]回文串(后缀自动机+manacher/回文自动机)
来源:互联网 发布:ipad广告拦截软件 编辑:程序博客网 时间:2024/06/04 18:15
传送门
题意:
给一个字符串s。定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。求出s的所有回文子串中的最
大出现值。
题解:
manacher求出所有本质不同的回文子串后在后缀自动机上二分。
(网上说的什么回文自动机感觉不清真啊。。)
#include<bits/stdc++.h>using namespace std;const int Maxn=6e5+50;char ch[Maxn],S[Maxn];int pos[Maxn],n,tot;long long ans;struct SAM{ int last,len[Maxn],cnt,link[Maxn][21],f[Maxn],son[Maxn][26],c[Maxn],que[Maxn]; SAM() { last=++cnt; }; inline void extend(int c,int o) { int p=last,np=last=++cnt;len[np]=len[p]+1; f[np]=1;pos[o]=np; while(!son[p][c]&&p)son[p][c]=np,p=link[p][0]; if(!p)link[np][0]=1; else { int q=son[p][c]; if(len[q]==len[p]+1)link[np][0]=q; else { int nq=++cnt;len[nq]=len[p]+1; memcpy(son[nq],son[q],sizeof(son[q])); link[nq][0]=link[q][0];link[q][0]=link[np][0]=nq; while(p&&son[p][c]==q)son[p][c]=nq,p=link[p][0]; } } } inline void init() { for(int i=1;i<=cnt;i++)c[len[i]]++; for(int i=1;i<=n;i++)c[i]+=c[i-1]; for(int i=cnt;i>=1;i--)que[c[len[i]]--]=i; for(int i=cnt;i>=1;i--) { int u=que[i]; if(link[u][0])f[link[u][0]]+=f[u]; } for(int i=1;i<=cnt;i++) { int u=que[i]; for(int j=1;j<=20;j++)link[u][j]=link[link[u][j-1]][j-1]; } } inline void query(int l,int r) { if(l&1)l++;if(r&1)r--; if(l>r)return; l/=2;r/=2; int p=pos[r],L=r-l+1; for(int i=20;i>=0;i--) { int y=link[p][i]; if(len[y]>=L)p=link[p][i]; } ans=max(ans,1ll*L*f[p]); }}sam;inline void manacher(){ static int R[Maxn]; int pos=1,mx=1; for(int i=2;i<tot;i++) { if(i>=mx)R[i]=1,sam.query(i,i); else R[i]=min(mx-i,R[pos*2-i]); while(S[i+R[i]]==S[i-R[i]]) { R[i]++; int l=i-R[i]+1,r=i+R[i]-1; sam.query(l,r); } if(i+R[i]>mx)mx=i+R[i],pos=i; }}int main(){ scanf("%s",ch+1); n=strlen(ch+1); for(int i=1;i<=n;i++)sam.extend(ch[i]-'a',i); sam.init(); S[0]='!';S[++tot]='#'; for(int i=1;i<=n;i++)S[++tot]=ch[i],S[++tot]='#'; S[++tot]='?'; manacher(); printf("%lld",ans);}
回文自动机:
#include<bits/stdc++.h>using namespace std;const int Maxn=3e5+50;char ch[Maxn],S[Maxn];int n,m,cnt,fail[Maxn],last,len[Maxn],son[Maxn][26],f[Maxn];inline int findfail(int x){ while(S[m-len[x]-1]!=S[m])x=fail[x]; return x;}int main(){ scanf("%s",ch+1); n=strlen(ch+1); S[0]='!'; fail[0]=1;last=0;len[1]=-1; cnt=1; for(int i=1;i<=n;i++) { S[++m]=ch[i]; int t=findfail(last); int c=ch[i]-'a'; if(!son[t][c]) { ++cnt; len[cnt]=len[t]+2; fail[cnt]=son[findfail(fail[t])][c]; son[t][c]=cnt; } last=son[t][c]; f[last]++; } long long ans=0; for(int i=cnt;i>=0;i--) { ans=max(ans,1ll*len[i]*f[i]); f[fail[i]]+=f[i]; } cout<<ans<<endl;}
阅读全文
0 0
- BZOJ3676: [Apio2014]回文串(后缀自动机+manacher/回文自动机)
- BZOJ3676:[Apio2014]回文串 (Manacher+后缀自动机+树上倍增)
- [BZOJ3676][Apio2014]回文串-后缀自动机+Manacher | | 回文树
- 【bzoj3676】[Apio2014]回文串 后缀自动机+倍增+manacher
- 【bzoj3676】[Apio2014]回文串 后缀自动机
- [BZOJ3676][Apio2014]回文串(回文自动机)
- bzoj3676 [Apio2014]回文串(回文自动机)
- [manacher 后缀自动机 || 回文自动机] BZOJ 3676 [Apio2014]回文串
- Bzoj3676:[Apio2014]回文串:回文自动机
- 【BZOJ3676】[Apio2014]回文串 【回文自动机】
- 回文自动机 模板 bzoj3676【Apio2014】回文串
- [回文自动机] BZOJ3676 [Apio2014] . 回文串
- BZOJ3676 [Apio2014]回文串 Manacher+后缀数据结构
- [bzoj3676][Apio2014]回文串 回文自动机(回文树)
- bzoj3676 回文串 回文自动机
- [BZOJ3676] [Apio2014]回文串 && Manacher + Hash
- BZOJ3676【回文自动机】
- bzoj3676: [Apio2014]回文串
- 关于BeanUtils.copyProperties的用法和优缺点
- java基础类的学习---Character类
- Qt两种定时器案例
- context应用启动时创建流程
- LintCode 最长回文子串
- BZOJ3676: [Apio2014]回文串(后缀自动机+manacher/回文自动机)
- oracle dataguard failover 功能测试
- 浅析---注解
- Ruby元编程-学习笔记(二)-方法
- 一句话木马常用方法
- [http]get post put delete 简介
- 目前刚接触码农世界没多久,知识有限
- HDU-6189 number number number(矩阵快速幂)
- ios带后缀名的字符串的截取