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. C#中HttpWebRequest的用法详解

    原文链接:http://www.cnblogs.com/love201314/p/5029312.html 1.HttpWebRequest和HttpWebResponse类是用于发送和接收HTTP数 ...

  2. access数据库 配置路径

    <configuration> <system.web> <compilation debug="true" targetFramework=&quo ...

  3. 2017.12.21-JQuery

    作业:密码加强验证 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> & ...

  4. [android] 优酷环形菜单-相对布局练习

    优酷环形菜单 布局文件,使用<RelativeLayout/>控件作为第一级菜单,相对布局,位于父控件的底部,水平居中,因为图片不是特别的标准,因此宽度和高度都钉死,宽度是高度的两倍 二次 ...

  5. Java JDBC MySQL

    一.驱动 下载地址:https://dev.mysql.com/downloads/connector/j/ 二.数据库连接配置 jdbc:mysql://address:port/database? ...

  6. POJ2236(KB5-A)

    Wireless Network Time Limit: 10000MS   Memory Limit: 65536K Total Submissions: 28617   Accepted: 118 ...

  7. mysql 添加用户

    CREATE USER 'user_name'@'%' IDENTIFIED BY '12345';      -- %  代表所有ip可以访问 GRANT all ON *.* TO 'user_n ...

  8. js-语言精粹-函数记忆

    函数可以将先前操作的结果记录在某个对象里,从而避免无谓的重复运算.这种优化方式被称为记忆(memoization).JavaScript的对象和数组要实现这种优化是非常方便的. 比如说,我们想要一个递 ...

  9. python unnitest 经验总结

    由于我的用例是数据驱动,每个用例保存为一个txt或者xls文件,执行时候需要读取文件,并将所有变量实例化成一个用例: 之前自己设计了框架,由于考虑需要生成一个美观通用的报告格式(原格式都是手写的htm ...

  10. su、sudo、su - root的区别

    su和sudo的区别 共同点:都是root用户权限: 不同点:su只获得root权限,工作环境不变,还是在切换之前用户的工作环境:sudo是完全获得root的权限和root的工作环境. sudo:表示 ...