由于本质不同的回文子串数量是O(n)的,考虑在对于每个回文子串在第一次找到它时对其暴力统计。可以发现manacher时若右端点移动则找到了一个新回文串。注意这样会漏掉串长为1的情况,特判一下。

  现在问题变为统计一个子串的出现次数。可以用SA,二分乱搞一下即可。这里使用SAM。以parent树上表示该子串的节点为起点,用倍增往上跳,找到深度最小的满足len限制的点就好了,出现次数就是其right集合的大小。

  uojAC,luoguRE一个点,bzojMLE……

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=;char c=getchar();
while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
return x*f;
}
#define N 600010
int n,last,cnt,len[N],fail[N],son[N][],size[N],pos[N>>],p[N];
long long ans=;
char s[N];
namespace tree
{
int p[N],t=,fa[N][];
struct data{int to,nxt;
}edge[N];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs(int k)
{
for (int i=p[k];i;i=edge[i].nxt)
{
fa[edge[i].to][]=k;
dfs(edge[i].to);
size[k]+=size[edge[i].to];
}
}
void build()
{
for (int i=;i<=cnt;i++) addedge(fail[i],i);
fa[][]=;dfs();
for (int j=;j<;j++)
for (int i=;i<=cnt;i++)
fa[i][j]=fa[fa[i][j-]][j-];
}
int calc(int l,int r)
{
int x=pos[r];
for (int j=;~j;j--) if (len[fa[x][j]]>=r-l+) x=fa[x][j];
return size[x];
}
}
using tree::calc;
void ins(int c,int n)
{
int x=++cnt,p=last;last=x;len[x]=n;size[x]=;pos[n]=x;
while (!son[p][c]&&p) son[p][c]=x,p=fail[p];
if (!p) fail[x]=;
else
{
int q=son[p][c];
if (len[p]+==len[q]) fail[x]=q;
else
{
int y=++cnt;len[y]=len[p]+;
memcpy(son[y],son[q],sizeof(son[q]));
fail[y]=fail[q];fail[q]=fail[x]=y;
while (son[p][c]==q) son[p][c]=y,p=fail[p];
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("bzoj3676.in","r",stdin);
freopen("bzoj3676.out","w",stdout);
const char LL[]="%I64d\n";
#else
const char LL[]="%lld\n";
#endif
last=cnt=;
scanf("%s",s+);n=strlen(s+);
for (int i=;i<=n;i++) ins(s[i]-,i);
tree::build();
for (int i=n;i>=;i--) s[i*-]=s[i];
for (int i=;i<n;i++) s[i<<]='$';
int x=;
for (int i=;i<=n;i++) ans=max(ans,1ll*calc(i,i));
for (int i=;i<n*;i++)
{
if (x+p[x]>i) p[i]=min(x+p[x]-i,p[x-(i-x)]);
while (i-p[i]->=&&i+p[i]+<n*&&s[i+p[i]+]==s[i-p[i]-])
{
p[i]++;
if (s[i+p[i]]!='$') ans=max(ans,1ll*((i+p[i]>>)-(i-p[i]>>)+)*calc((i-p[i]>>)+,(i+p[i]>>)+));
}
if (i+p[i]>x+p[x]) x=i;
}
cout<<ans;
return ;
}

BZOJ3676 APIO2014回文串(manacher+后缀自动机)的更多相关文章

  1. [bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增

    Brief Description 一个回文串的value定义为这个回文串的长度乘以出现次数.给定一个字符串,求\(value_{max}\). Algorithm Design 我们使用Manach ...

  2. [Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 3396  Solved: 1568[Submit][Statu ...

  3. 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)

    传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...

  4. [BZOJ3676][APIO2014]回文串(Manacher+SAM)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 3097  Solved: 1408[Submit][Statu ...

  5. BZOJ3676 APIO2014 回文串 Manacher、SA

    传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...

  6. [APIO2014]回文串 manacher 后缀数组

    题面:洛谷 题解: 还是这个性质:对于每个串而言,本质不同的回文串最多只有O(n)个. 所以我们先求出这O(n)个本质不同的回文串,然后对整个串求一次sa. 然后对于每个回文串,求出它的出现次数,更新 ...

  7. bzoj 3676: [Apio2014]回文串【后缀自动机+manacher】

    用manacher找出本质不同的回文子串放在SAM上跑 #include<iostream> #include<cstdio> #include<cstring> ...

  8. [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串

    回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...

  9. bzoj3676 [Apio2014]回文串 卡常+SAM+树上倍增

    bzoj3676 [Apio2014]回文串 SAM+树上倍增 链接 bzoj luogu 思路 根据manacher可以知道,每次暴力扩展才有可能出现新的回文串. 所以推出本质不同的回文串个数是O( ...

随机推荐

  1. 用statefulSet 部署持久化的OA(Tomcat)

    1.部署多个副本的OA(Tomcat)集群,其中一个Tomcat的需要加一个定时器,其他代码跟其他的Tomcat的代码一样.需要重启后也还是保持这个状态.代码如下: apiVersion: v1 ki ...

  2. SkylineGlobe Android 开发 面积计算示例代码

    SkylineGlobe Android 开发 面积计算示例代码: 如果之前熟悉SkylineGlobe桌面端的二次开发,看这些代码应该不难理解. package com.skyline.terrae ...

  3. Java多线程编程模式实战指南(二):Immutable Object模式

    多线程共享变量的情况下,为了保证数据一致性,往往需要对这些变量的访问进行加锁.而锁本身又会带来一些问题和开销.Immutable Object模式使得我们可以在不使用锁的情况下,既保证共享变量访问的线 ...

  4. Django框架知识点整理

    1.安装django, pip install django 或者是通过 “==”符号指定版本号. 2.创建一个Django项目: django-admin createproject project ...

  5. .NET Core 3.0 跟踪

    Preview1: https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-net-core-3-preview-1-and-ope ...

  6. 【IDEA】Intellij IDEA创建的Web项目配置Tomcat并启动Maven项目

    转载请注明出处:http://blog.csdn.net/qq_26525215本文源自[大学之旅_谙忆的博客] 本篇博客讲解IDEA如何配置Tomcat. 大部分是直接上图哦. 点击如图所示的地方, ...

  7. 基于HTML5 Canvas 实现地铁站监控

    伴随国内经济的高速发展,人们对安全的要求越来越高.为了防止下列情况的发生,您需要考虑安装安防系统: 提供证据与线索:很多工厂银行发生偷盗或者事故相关机关可以根据录像信息侦破案件,这个是非常重要的一个线 ...

  8. B树、B-树、B+树、B*树相关

    B树 即二叉搜索树: 1.所有非叶子结点至多拥有两个儿子(Left和Right): 2.所有结点存储一个关键字: 3.非叶子结点的左指针指向小于其关键字的子树,右指针指向大于其关键字的子树: 如: B ...

  9. linux-IO重定向-文本流重定向

    输出重定向的追加和覆盖 标准输出就这两种: 覆盖和追加 >> 是重定向操作符 1 是 命令的文件描述符 重定向操作符合文件描述符之间不能存在空白符 否则1会被当做是文件被读取 将正确和错误 ...

  10. 剑指offer:树的子结构

    题目描述: 输入两棵二叉树A,B,判断B是不是A的子结构.(ps:我们约定空树不是任意一个树的子结构) 解题思路: 同样考虑用递归来做. 利用两个递归函数,一个用于判断两棵树树否相等,另一个递归取A的 ...