Description

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

Input

输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。

Output

输出一个整数,为逝查回文子串的最大出现值。

Sample Input

【样例输入l】
abacaba
【样例输入2]
www

Sample Output

【样例输出l】
7
【样例输出2]
4

HINT

一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。
在第一个样例中,回文子串有7个:a,b,c,aba,aca,bacab,abacaba,其中:
● a出现4次,其出现值为4:1:1=4
● b出现2次,其出现值为2:1:1=2
● c出现1次,其出现值为l:1:l=l
● aba出现2次,其出现值为2:1:3=6
● aca出现1次,其出现值为1=1:3=3
●bacab出现1次,其出现值为1:1:5=5
● abacaba出现1次,其出现值为1:1:7=7
故最大回文子串出现值为7。
【数据规模与评分】
数据满足1≤字符串长度≤300000。

Solution

垃圾题目卡$SAM+Manacher$做法的空间……害我把所有的结构体全拆开还把$SAM$的$son$数组换成了$map$才过……

首先众所周知,一个串的本质不同的回文子串只有$O(n)$级别,且在$Manacher$过程中右端点右移的情况就是本质不同的回文子串。所以我们可以做一遍$Manacher$把本质不同的回文子串求出来。

假设现在的一个回文子串是$S_{l,r}$,设$SAM$插入$r$的时候的$np$节点为$node_r$,那么我们知道,$S_{l,r}$一定是$node_r$代表的子串的一个后缀,且$S_{l,r}$的出现次数是$right_{node_r}$。

我们可以倍增从$node_r$往上跳,因为越往上跳$right$越大。跳到长度取值范围包括$r-l+1$的节点然后更新答案就可以了。

Code

 #include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
#define N (600009)
#define LL long long
using namespace std; int to[N],nxt[N];
int n,m,pos[N],len[N];
int Depth[N],f[N][];
int head[N],num_edge;
int p,q,np,nq,last=,cnt=;
int fa[N],rig[N],step[N],node[N];
map<int,int>son[N];
LL ans;
char s[N>>],t[N]; void add(int u,int v)
{
to[++num_edge]=v;
nxt[num_edge]=head[u];
head[u]=num_edge;
} void Insert(int x)
{
p=last; np=last=++cnt; step[np]=step[p]+; rig[np]=;
while (!son[p][x] && p) son[p][x]=np, p=fa[p];
if (!p) fa[np]=;
else
{
q=son[p][x];
if (step[q]==step[p]+) fa[np]=q;
else
{
nq=++cnt; step[nq]=step[p]+;
son[nq]=son[q];
fa[nq]=fa[q]; fa[q]=fa[np]=nq;
while (son[p][x]==q) son[p][x]=nq, p=fa[p];
}
}
} void DFS(int x,int fa)
{
Depth[x]=Depth[fa]+; f[x][]=fa;
for (int i=; i<=; ++i) f[x][i]=f[f[x][i-]][i-];
for (int i=head[x]; i; i=nxt[i])
DFS(to[i],x), rig[x]+=rig[to[i]];
} void Calc()
{
for (int i=; i<n; ++i) Insert(s[i]-'a'), node[i]=np;
for (int i=; i<=cnt; ++i) add(fa[i],i);
DFS(,);
} void Solve(int p,int k)
{
while (t[p+k]=='#' || t[p+k]==')') --k;
int x=node[pos[p+k]],y=pos[p+k]-pos[p-k]+;
for (int i=; i>=; --i) if (step[f[x][i]]>=y) x=f[x][i];
ans=max(ans,1ll*rig[x]*y);
} void Manacher()
{
t[++m]='(';
for (int i=; i<n; ++i) t[++m]='#', t[++m]=s[i], pos[m]=i;
t[++m]='#'; t[++m]=')'; int x,mid=,maxn=;
for (int i=; i<=m; ++i)
{
if (i>maxn) x=;
else x=min(maxn-i+,len[mid*-i]);
while (t[i+x]==t[i-x]) Solve(i,x), ++x;
len[i]=x;
if (i+x->maxn) maxn=i+x-, mid=i;
}
} int main()
{
scanf("%s",s); n=strlen(s);
Calc(); Manacher();
printf("%lld\n",ans);
}

BZOJ3676:[APIO2014]回文串(SAM,Manacher)的更多相关文章

  1. BZOJ3676 APIO2014回文串(manacher+后缀自动机)

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

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

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

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

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

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

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

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

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

  6. BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)

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

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

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

  8. BZOJ3676 APIO2014 回文串 Manacher、SA

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

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

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

随机推荐

  1. JS存储cookie读取cookie删除cookie详细用法

    假设有这样一种情况,在某个用例流程中,由A页面跳至B页面,若在A页面中采用JS用变量temp保存了某一变量的值,在B页面的时候,同样需要使用JS来引用temp的变量值,对于JS中的全局变量或者静态变量 ...

  2. Nodejs学习事件模块

    1.nodejs 版本为v6.2.0,events是node.js 最重要的模块,events模块只提供了一个对象EventEmitter,EventEmitter 的核心是事件发射与事件监听器.可以 ...

  3. C# 导出Excel表格

    function exportExcel() { //查询条件 var startTime = F.ui.startTime.getText() == "" ? null : F. ...

  4. Oracle数据库操作---入门(一)

    由于工作原因,近期可能会开始多复习一些数据库相关的知识了,想深入了解的,也可以一起复习.学习~ 前期先巩固一下基础操作,后期会一点点的加深向运维方向深入.开篇主要介绍一些数据库理论知识,不感兴趣的可以 ...

  5. 聊聊Java内存模型

    一.Java内存模型 硬件处理 电脑硬件,我们知道有用于计算的cpu.辅助运算的内存.以及硬盘还有进行数据传输的数据总线.在程序执行中很多都是内存计算,cpu为了更快的进行计算会有高速缓存,最后同步至 ...

  6. Mybatis逆向生成代碼

    Idea 单模块 1.在pom.xml中添加依赖 <build> <plugins> <plugin> <groupId>org.mybatis.gen ...

  7. php根据命令行参数生成配置文件

    像npm, composer等工具,在开始使用的使用,都需要初始化项目,生成一个项目的配置文件.这种功能的原理是怎么实现的呢? 比如: D:\>npm init --yes Wrote to D ...

  8. 使用ThinkPHP实现生成/校验验证码功能

    首先了解父类Verity.class.php(ThinkPHP/Library/Think/Verity.class.php)中的一些函数 1:check() 校验验证码是否正确 2:entry()输 ...

  9. OSGI企业应用开发(九)整合Spring和Mybatis框架(二)

    上篇文章中,我们完成了在OSGI应用中整合Spring和Mybatis框架的准备工作,本节我们继续Spring和Mybatis框架的整合. 一.解决OSGI整合Spring中的Placeholder问 ...

  10. jQuery事件和JSON点语法

    <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" ...