bzoj3676:回文串(manacher+SAM的parent树上倍增)
来源:互联网 发布:element linux 编辑:程序博客网 时间:2024/05/29 17:41
模拟考是碰到的,以前听过但没有做过,当场推出来了。
题面
题意就是给你一个串,定义字串的得分为长度*出现次数,问所有回文串中的最大得分。
题目分析:回文串当然首推manacher算法,只有当右指针右移时才会出现本质不同的回文串,得到该串的l和r,然后就是统计该串出现次数,很水的的我只会SAM了。
SAM的每个状态的所有串互为后缀,还记下了Right集,大小即为这个状态所有串的出现次数,还有Min和Max,表示这些串的长度范围,Min=Max(pre)+1。
先找到插入第r个字符时的状态,然后以Max为二分依据在parent树上倍增,找到字串[l,r]所属的状态,并统计答案。
#include <iostream>#include <fstream>#include <algorithm>#include <cmath>#include <ctime>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define mmst(a, b) memset(a, b, sizeof(a))#define mmcp(a, b) memcpy(a, b, sizeof(b))typedef long long LL;const int N=300300,mo=1e9+7;char s[N],ss[2*N];int n;int last=1,cur=1;int pos[N],dep[2*N],pre[2*N],son[2*N][26],fa[2*N][20],siz[2*N];int bl[N*2];LL ans;struct yy{ int num,de;}f[N*2];bool cmp(yy x,yy y){ return x.de<y.de;}void insert(int x,int id){ dep[++cur]=dep[last]+1; int np=cur,p=last; last=cur; pos[id]=cur; siz[cur]=1; for(;!son[p][x];p=pre[p]) son[p][x]=np; if(!p) pre[np]=1; else { int q=son[p][x]; if(dep[q]==dep[p]+1) pre[np]=q; else { dep[++cur]=dep[p]+1; int nq=cur; pre[nq]=pre[q]; pre[q]=pre[np]=nq; mmcp(son[nq],son[q]); for(;son[p][x]==q;p=pre[p]) son[p][x]=nq; } }}void query(int l,int r){ if(l%2==0||r%2==0) return; l=(l+1)/2; r=(r+1)/2; int mid=pos[r]; for(int j=18;j>=0;j--) { int t=fa[mid][j]; if(dep[t]>=r-l+1) mid=t; } ans=max(ans,1ll*(r-l+1)*siz[mid]);}void manacher(){ int ret=0,mx=0,id=0; bl[0]=1; for(int i=0;i<=n;i++) ss[i*2]='&'; for(int i=0;i<n;i++) ss[i*2+1]=s[i]; ss[2*n]='!'; for(int i=1;i<n*2+1;i++) { if(mx>i) bl[i]=min(bl[2*id-i],mx-i); else { bl[i]=1; query(i,i); } while(ss[i-bl[i]]==ss[i+bl[i]]) { query(i-bl[i],i+bl[i]); bl[i]++; } if(mx<=bl[i]+i) mx=bl[i]+i-1,id=i; }}int main(){ freopen("2115.in", "r", stdin); freopen("2115.out", "w", stdout); scanf("%s",s); n=strlen(s); for(int i=0;i<n;i++) insert(s[i]-'a',i+1); for(int i=1;i<=cur;i++) fa[i][0]=pre[i]; fa[1][0]=1; for(int j=1;j<=18;j++) for(int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; for(int i=1;i<=cur;i++) { f[i].num=i; f[i].de=dep[i]; } sort(f+1,f+cur+1,cmp); for(int i=cur;i>=1;i--) { int hy=f[i].num; siz[pre[hy]]+=siz[hy]; } manacher(); cout<<ans<<endl; return 0;}
阅读全文
1 0
- bzoj3676:回文串(manacher+SAM的parent树上倍增)
- BZOJ3676:[Apio2014]回文串 (Manacher+后缀自动机+树上倍增)
- 【bzoj3676】[Apio2014]回文串 后缀自动机+倍增+manacher
- BZOJ3676: [Apio2014]回文串(后缀自动机+manacher/回文自动机)
- [BZOJ3676] [Apio2014]回文串 && Manacher + Hash
- BZOJ3676 [Apio2014]回文串 Manacher+后缀数据结构
- [BZOJ3676][Apio2014]回文串-后缀自动机+Manacher | | 回文树
- bzoj3676 [Apio2014]回文串(manacher+SA+二分+lcp)
- [BZOJ3676][Apio2014]回文串(回文自动机)
- BZOJ3676 回文串 (回文树)
- bzoj3676 [Apio2014]回文串(回文自动机)
- NKOJ 2844 (APIO 2014)回文串(Manacher+后缀自动机+倍增/回文树)
- bzoj3676: [Apio2014]回文串
- 【APIO2014】【BZOJ3676】回文串
- BZOJ3676: [Apio2014]回文串
- [bzoj3676][APIO2014]回文串
- bzoj3676【APIO2014】回文串
- BZOJ3676: [Apio2014]回文串
- iOS | 小心NSTimer中的循环引用
- 软件架构模式转载
- UVA
- jumpserver堡垒机名词
- python实例(字符串判断)
- bzoj3676:回文串(manacher+SAM的parent树上倍增)
- dlopen failed: "/data/app-lib/XXX/XXX.so" has unexpected e_machine: 40
- 通过hadoop streaming 输入两个文件或目录
- 论文阅读-《CoupleNet:Coupling Global Structure with Local Parts for Object Detection》
- Linux系统管理命令
- SpringMVC/SpringBoot使用easypoi实现Excel文件导入导出功能实现
- 恶意代码分析实战 课后题 Lab12-01
- 说一说gc
- 《奔跑吧Linux内核》之处理器体系结构