题目大意:

给你一个字符串,求其中回文子串的长度*出现次数的最大值

明明是PAM裸题我干嘛要用SAM做

回文子串有一个神奇的性质,一个字符串本质不同的回文子串个数是$O(n)$级别的

用$manacher$的思想分析一下,$maxright$指针向右扩展才会产生新的回文串

其它的回文串都根据之前求得的信息得到的,比如根据回文中心对称,或者是不超过当前最长回文上限

每次扩展成功时,都把这个回文串放到$SAM$里跑

预处理出每个前缀结尾在$SAM$里的节点编号,就不用每次都从头跑了

沿着$pre$指针倍增地往上跳,直到跳到当前节点能表示出这个回文串为止

注意长度为1的串的情况

如果被卡空间了,会发现预处理以后,trs指针没什么用了,把它当成倍增的数组吧

 #include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 305000
#define S1 (N1<<1)
#define T1 (N1<<2)
#define ll long long
#define uint unsigned int
#define rint register int
#define dd double
#define il inline
#define inf 0x3f3f3f3f
#define idx(X) (X-'a')
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
int n,m,len;
/*struct Edge{
int head[S1],to[S1],nxt[S1],cte;
void ae(int u,int v){
cte++;to[cte]=v,nxt[cte]=head[u],head[u]=cte;}
}E;*/
namespace SAM{
int trs[S1][],pre[S1],dep[S1],ed[S1],pos[S1],la,tot;
void init(){tot=la=;}
void insert(int c,int id)
{
int p=la,np=++tot,q,nq;la=np;
dep[np]=dep[p]+;
pos[id]=np,ed[np]=;
for(;p&&!trs[p][c];p=pre[p]) trs[p][c]=np;
if(!p) {pre[np]=;return;}
q=trs[p][c];
if(dep[q]==dep[p]+) pre[np]=q;
else{
pre[nq=++tot]=pre[q];
pre[q]=pre[np]=nq;
dep[nq]=dep[p]+;
memcpy(trs[nq],trs[q],sizeof(trs[q]));
for(;p&&trs[p][c]==q;p=pre[p]) trs[p][c]=nq;
}
}
int hs[S1],que[S1],sz[S1];
//int ff[S1][20];
void build()
{
int i,j,x;
for(i=;i<=tot;i++) hs[dep[i]]++;
for(i=;i<=n;i++) hs[i]+=hs[i-];
for(i=;i<=tot;i++) que[hs[dep[i]]--]=i;
for(i=tot;i;i--)
{
x=que[i];//E.ae(pre[x],x);
if(ed[x]) sz[x]++;
sz[pre[x]]+=sz[x];
trs[x][]=x,trs[x][]=pre[x];
}
for(j=;j<=;j++)
for(i=;i<=tot;i++)
trs[i][j]=trs[ trs[i][j-] ][j-];
}
int solve(int x,int s,int e)
{
int fx,L=e-s+;
for(int j=;j>=;j--)
//for(int j=5;j>=0;j--)
{
if(!trs[x][j]) continue;
fx=trs[x][j];
if(dep[fx]>=L) x=fx;
}
return sz[x];
}
};
char str[N1],man[S1];
int p[S1],hs[]; int main()
{
//freopen("t1.in","r",stdin);
scanf("%s",str+);
n=strlen(str+);
man[]='$',man[]='#';
int i,j,mr=,mid=,l,r,x;
SAM::init();
for(i=;i<=n;i++) SAM::insert(idx(str[i]),i);
SAM::build();
for(i=;i<=n;i++) man[*i]=str[i],man[*i+]='#';
p[]=;
ll ans=;
for(i=;i<=*n+;i++)
{
if(i<mr) p[i]=min(p[*mid-i],mr-i);
else p[i]=;
while(man[i-p[i]]==man[i+p[i]])
{
if(!((i+p[i])&))
{
l=(i-p[i])>>;
r=(i+p[i])>>;
x=SAM::pos[r];
ans=max(ans,1ll*(r-l+)*SAM::solve(x,l,r));
}
p[i]++;
}
if(i+p[i]>mr) mr=i+p[i],mid=i;
}
for(i=;i<=n;i++)
if(!hs[idx(str[i])])
{
hs[idx(str[i])]=;
l=i,r=i,x=SAM::pos[r];
ans=max(ans,1ll*SAM::solve(x,l,r));
}
printf("%lld\n",ans);
return ;
}

进入正题

这明明是一道$PAM$裸题嘛

$PAM$的构造方式类似于$AC$自动机..但它仍然有许多美妙的性质

比如奇回文树是树根节点深度设为-1等等...

而且$PAM$代码非常短

 #include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 301000
#define S1 (N1<<1)
#define ll long long
#define uint unsigned int
#define rint register int
#define dd double
#define il inline
#define inf 0x3f3f3f3f
#define idx(X) (X-'a')
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
int n,len,cnt;
namespace PAM{
int trs[N1][],pre[N1],dep[N1],sz[N1],la,tot;
void init(){la=tot=,pre[]=pre[]=,dep[]=-;}
int ntsym(char *str,int i,int p){return str[i-dep[p]-]!=str[i]?:;}
void insert(char *str,int i)
{
int p=la,np,fp,c=idx(str[i]);
while(ntsym(str,i,p)) p=pre[p];
if(!trs[p][c])
{
np=++tot;
dep[np]=dep[p]+;
fp=pre[p];
while(ntsym(str,i,fp)) fp=pre[fp];
pre[np]=trs[fp][c];
trs[p][c]=np;
}
la=trs[p][c];
sz[trs[p][c]]++;
return;
}
ll topo()
{
ll ans=;
for(int x=tot;x>;x--)
sz[pre[x]]+=sz[x],ans=max(ans,1ll*dep[x]*sz[x]);
return ans;
}
};
char str[N1]; int main()
{
//freopen("t2.in","r",stdin);
//freopen("a.out","w",stdout);
int i;PAM::init();
scanf("%s",str+);len=strlen(str+);
for(i=;i<=len;i++) PAM::insert(str,i);
printf("%lld\n",PAM::topo());
return ;
}

BZOJ 3676 [Apio2014]回文串 (后缀自动机+manacher/回文自动机)的更多相关文章

  1. [bzoj3676]回文串[后缀数组+Manacher]

    后缀数组+Manacher #include <iostream> #include <cstdio> #include <cstdlib> #include &l ...

  2. 力扣算法:125-验证回文串,131-分割回文串---js

    LC 125-验证回文串 给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,可以忽略字母的大小写. 说明:本题中,我们将空字符串定义为有效的回文串. 注:回文串是正着读和反着读都一样的字符串. ...

  3. bzoj 3676: [Apio2014]回文串 回文自动机

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 844  Solved: 331[Submit][Status] ...

  4. 字符串(马拉车算法,后缀数组,稀疏表):BZOJ 3676 [Apio2014]回文串

    Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行 ...

  5. bzoj 3676: [Apio2014]回文串【回文自动机】

    回文自动机板子 或者是SAM+manacher+倍增,就是manacher求本质不同回文串(让f++的串),然后在SAM倍增查询对应点出现次数 #include<iostream> #in ...

  6. BZOJ 3676: [Apio2014]回文串

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2013  Solved: 863[Submit][Status ...

  7. 【BZOJ 3676】 3676: [Apio2014]回文串 (SAM+Manacher+倍增)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2343  Solved: 1031 Description 考 ...

  8. bzoj 3676 [Apio2014]回文串(Manacher+SAM)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3676 [题意] 给定一个字符串,定义一个串的权值为长度*出现次数,求最大权的回文子串. ...

  9. ●BZOJ 3676 [Apio2014]回文串

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3676 题解: 后缀数组,Manacher,二分 首先有一个结论:一个串的本质不同的回文串的个 ...

随机推荐

  1. UNIX时间转换ASP代码.txt

    '参数:strTime:要转换的时 间:intTimeZone:该时间对应的时区 '返回值:strTime相对于1970年1月1日午夜0点经过的秒数 '示例:ToUnixTime("2008 ...

  2. SpringBoot2整合activiti6环境搭建

    SpringBoot2整合activiti6环境搭建 依赖 <dependencies> <dependency> <groupId>org.springframe ...

  3. 2019年北航OO第四单元(UML任务)及学期总结

    第四单元两次作业总结 第十三次作业 需求分析 本次作业需要完成一个UML类图解析器,所需要解析的只有符合UML标准和能够在Java 8中复现的UML类图.查询指令存在两种:仅与所查对象有关的指令,以及 ...

  4. DOM中元素节点,属性节点,文本节点的理解

    节点信息 每个节点都拥有包含着关于节点某些信息的属性.这些属性是: nodeName(节点名称) nodeValue(节点值) nodeType(节点类型) nodeType nodeType 属性可 ...

  5. ASP.NET CORE--WIN10上无法单步调试解决方法

    参考这篇文章 http://www.cnblogs.com/artech/p/debug-in-vs-code.html In order to be able to debug cross-plat ...

  6. Eclipse中项目去除Js验证

    删除项目.project文件中的 <buildCommand>   <name>org.eclipse.wst.jsdt.core.javascriptValidator< ...

  7. C++ 嵌入汇编程序提高计算效率

    因为汇编语言比C++更接近硬件底层,所以在性能要求高的程序中往往能够採取在C++代码中嵌入汇编的方式来给程序提速. 在VC中能够简单的通过 __asm { //在这里加入汇编代码 } 来实现. 以下通 ...

  8. sql查询语句中的乱码 -- 前面加N

    直接运行sql出出现乱码,在中文字符前加N就能够正常显示了.N的含义就是用nvarchar格式显示.

  9. python爬虫系列序

    关于爬虫的了解,始于看到这篇分析从数据角度解析福州美食,和上份工作中的短暂参与. 长长短短持续近一年的时间,对其态度越来越明晰,噢原来这就是我想从事的工作. 于是想要系统学习的心理便弥散开来…… 参考 ...

  10. C# DispatcherTimer Start之后立即执行

    如果DispatherTimer 的Interval 不是在实例化时赋值,那么Start之后,Tick方法会立即执行一次. DispatcherTimer timer = new Dispatcher ...