#103. 【APIO2014】Palindromes

统计

给你一个由小写拉丁字母组成的字符串 ss。我们定义 ss 的一个子串的存在值为这个子串在 ss 中出现的次数乘以这个子串的长度。

对于给你的这个字符串 ss,求所有回文子串中的最大存在值。

输入格式

一行,一个由小写拉丁字母(a~z)组成的非空字符串 ss。

输出格式

输出一个整数,表示所有回文子串中的最大存在值。

样例一

input

abacaba

output

7

explanation

用 ∣s∣∣s∣ 表示字符串 ss 的长度。

一个字符串 s1s2…s∣s∣s1s2…s∣s∣ 的子串是一个非空字符串 sisi+1…sjsisi+1…sj,其中 1≤i≤j≤∣s∣1≤i≤j≤∣s∣。每个字符串都是自己的子串。

一个字符串被称作回文串当且仅当这个字符串从左往右读和从右往左读都是相同的。

这个样例中,有 77 个回文子串 a,b,c,aba,aca,bacab,abacaba。他们的存在值分别为 4,2,1,6,3,5,74,2,1,6,3,5,7。

所以回文子串中最大的存在值为 77。

样例二

input

www

output

4

限制与约定

第一个子任务共 8 分,满足 1≤∣s∣≤1001≤∣s∣≤100。

第二个子任务共 15 分,满足 1≤∣s∣≤10001≤∣s∣≤1000。

第三个子任务共 24 分,满足 1≤∣s∣≤100001≤∣s∣≤10000。

第四个子任务共 26 分,满足 1≤∣s∣≤1000001≤∣s∣≤100000。

第五个子任务共 27 分,满足 1≤∣s∣≤3000001≤∣s∣≤300000。

时间限制:1s1s

空间限制:256MB256MB

下载

样例数据下载

思路:

1、manacher找出回文串

2、suffix数组向上向下二分找出串t出现次数

3、用RMQ加速

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=3e5+;
typedef long long ll;
int n,p[N<<],f[N][],log2[N];
char s[N],S[N<<];
int c[N],h[N],sa[N],tsa[N],rank[N],trank[N];
ll ans;
void DA(int maxx=){
int p;
for(int i=;i<=maxx;i++) c[i]=;
for(int i=;i<=n;i++) c[rank[i]=s[i]]++;
for(int i=;i<=maxx;i++) c[i]+=c[i-];
for(int i=n;i;i--) sa[c[rank[i]]--]=i;
trank[sa[]]=p=;
for(int i=;i<=n;i++){
if(rank[sa[i]]!=rank[sa[i-]]) p++;
trank[sa[i]]=p;
}
for(int i=;i<=n;i++) rank[i]=trank[i];
for(int k=;p<n;k<<=,maxx=p){
p=;
for(int i=n-k+;i<=n;i++) tsa[++p]=i;
for(int i=;i<=n;i++) if(sa[i]>k) tsa[++p]=sa[i]-k;
for(int i=;i<=maxx;i++) c[i]=;
for(int i=;i<=n;i++) trank[i]=rank[tsa[i]];
for(int i=;i<=n;i++) c[trank[i]]++;
for(int i=;i<=maxx;i++) c[i]+=c[i-];
for(int i=n;i;i--) sa[c[trank[i]]--]=tsa[i];
trank[sa[]]=p=;
for(int i=;i<=n;i++){
if(rank[sa[i]]!=rank[sa[i-]]||rank[sa[i]+k]!=rank[sa[i-]+k]) p++;
trank[sa[i]]=p;
}
for(int i=;i<=n;i++) rank[i]=trank[i];
}
for(int i=,k=;i<=n;i++){
int j=sa[rank[i]-];
while(s[i+k]==s[j+k]) k++;
h[rank[i]]=k;if(k>) k--;
}
}
void RMQ(){
for(int i=;i<=n;i++) f[i][]=h[i];
for(int i=;i<=n;i++) log2[i]=log2[i>>]+;
for(int j=;j<=log2[n];j++){
for(int i=;i+(<<j)-<=n;i++){
f[i][j]=min(f[i][j-],f[i+(<<j-)][j-]);
}
}
}
int query(int l,int r){
if(l>r) return ;//WA*1
int k=log2[r-l+];
return min(f[l][k],f[r-(<<k)+][k]);
}
ll solve(int l,int r){
if(l>r) return ;//WA*1
int pos=rank[l],L=,R=pos,up=pos,dn=pos;
while(L+<R){//WA*1
int mid=L+R>>;
if(query(mid+,pos)>=r-l+) R=mid,up=mid;
else L=mid;
}
L=pos,R=n+;//WA*1
while(L+<R){
int mid=L+R>>;
if(query(pos+,mid)>=r-l+) L=mid,dn=mid;
else R=mid;
}
return 1LL*(dn-up+)*(r-l+);
}
int opl,opr,lal=-,rar=-;
void find(char c,int pos,int d){//WA*1
bool f=;
if(c!='#') pos++;else f=;
pos/=;d/=;
opr=pos+d;
pos-=d;
if(f) pos++;
opl=pos;
}
void manacher(){
int l=-;
for(int i=;i<=n;i++) S[++l]='#',S[++l]=s[i];
S[++l]='#';
int id=,mx=-;ll t;
for(int i=;i<l;i++){
if(id+mx>i) p[i]=min(p[id*-i],id+mx-i);
while(i-p[i]->=&&i+p[i]+<=l&&S[i-p[i]-]==S[i+p[i]+]){
p[i]++;
if(id+mx<i+p[i]){
find(S[i],i,p[i]);
if(opl==lal&&opr==rar) continue;
lal=opl;rar=opr;//TLE*1
t=solve(opl,opr);
if(ans<t) ans=t;
}
}
if(id+mx<i+p[i]) id=i,mx=p[i];
}
}
int main(){
scanf("%s",s+);n=strlen(s+);
DA();RMQ();//WA*1
manacher();
cout<<ans;
return ;
}

【APIO2014】Palindromes的更多相关文章

  1. UOJ #103:【APIO2014】Palindromes

    题意: 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. 学会马拉车之后发现还需要后缀数组才能AC ...

  2. UOJ#103. 【APIO2014】Palindromes PAM模板题

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ103.html 前言 我终于会PAM啦 感谢CLY大佬手把手教我PAM 题解 建个 PAM. 统计一下每一个节点的 Rig ...

  3. 【BZOJ】【3676】【APIO2014】回文串

    回文自动机/Manacher+SA 这道题可以用Manacher找出本质不同的回文串(令max增大的所有回文串),然后再用SA跑出来有多少相同. 还有一种做法就是回文自动机(Orz Hzwer)的裸题 ...

  4. 【BZOJ】【3675】【APIO2014】序列分割

    DP+斜率优化 首先我们根据这个分割的过程可以发现:总得分等于k+1段两两的乘积的和(乘法分配律),也就是说与分割顺序是无关的. 再对乘积进行重分组(还是乘法分配律)我们可以转化为:$ans=\sum ...

  5. bzoj3675【APIO2014】序列切割

    3675: [Apio2014]序列切割 Time Limit: 40 Sec  Memory Limit: 128 MB Submit: 1468  Solved: 607 [Submit][Sta ...

  6. UOJ#104. 【APIO2014】Split the sequence 动态规划 斜率优化

    原文链接www.cnblogs.com/zhouzhendong/p/UOJ104.html 题解 首先证明一个结论:对于一种分割方案,分割的顺序不影响最终结果. 证明:对于树 a[x] 和 a[y] ...

  7. 【BZOJ3675】【Apio2014】序列分割

    Description 传送门 Solution ​ 之前我也遇到过一次这种"两段之和乘积作为贡献"的问题:考虑把这一种\((\sum) *(\sum)\)的形式拆括号,就可以发现 ...

  8. BZOJ 3676 【APIO2014】 回文串

    题目链接:回文串 我终于也会回文自动机辣! 其实吗……我觉得回文自动机(听说这玩意儿叫\(PAM\))还是比较\(simple\)的……至少比\(SAM\)友善多了…… 所谓回文自动机,每个节点就代表 ...

  9. 【UOJ #105】【APIO2014】Beads and wires

    http://uoj.ac/problem/105 好神的dp啊. 确定一个点为根之后,蓝线只能是竖着的,不能横跨兄弟. 枚举每个点为根进行树形dp是\(O(n^2)\)的,\(f(x,0/1)\)表 ...

随机推荐

  1. Python中给文件加锁

    首先要引入库import fcntl打开一个文件f = open('./test')对该文件加密:fcntl.flock(f, fcntl.LOCK_EX)这样就对文件test加锁了,如果有其他进程要 ...

  2. ubuntu下配置.net core运行环境

    Ubuntu 16.4执行: sudo sh -c 'echo "deb [arch=amd64] https://apt-mo.trafficmanager.net/repos/dotne ...

  3. c# 读取文件流

    1.获取文件路径 2.编写读取路径文件信息 private string ReadFileStream(string filePath)         {             string st ...

  4. 2012全球SEO行业调查报告

    这份报告是SEOmoz对每两年一度举办的SEO行业调查进行的分析数据,上次调查是在2010年.该调查,主要围绕SEO从业人员的特征.工作内容时间分配比例.SEO相关消费和预算.对未来市场的看法.seo ...

  5. 通过使用JanusGraph索引提高性能

    翻译整理:纪玉奇 Extending JanusGraph Server JanusGraph支持两种类型的索引:graph index和vertex-centric index.graph inde ...

  6. ss - float浮动模块的高度问题 解决方案

    当一个Div中的子元素都是浮动元素时,该div是没有高度的.通常会带来很多困扰,解决方案如下: 低版本统配兼容: overflow: hidden; 下面是不支持低配浏览器,而且似乎该效果对 P 标签 ...

  7. MySQL怎样存储IP地址

    为什么要问如何存储IP 首先就来阐明一下部分人得反问:为什么要问IP得怎样存,直接varchar类型不就得了吗? 其实做任何程序设计都要在功能实现的基础上最大限度的优化性能.而数据库设计是程序设计中不 ...

  8. 我的Android进阶之旅------&gt;Android关于Activity管理的一个简单封装

    怎样管理当前的执行Activity栈,怎样彻底退出程序.本文封装了一个Activity管理类,能够方便随时退出程序. import java.util.Stack; import android.ap ...

  9. Atitti. 语法树AST、后缀表达式、DAG、三地址代码

    Atitti. 语法树AST.后缀表达式.DAG.三地址代码 抽象语法树的观点认为任何复杂的语句嵌套情况都可以借助于树的形式加以描述.确实,不得不承认应用抽象语法树可以使语句翻译变得相对容易,它很好地 ...

  10. Vivado使用技巧:封装自己设计的IP核

    概述   Vivado在设计时可以感觉到一种趋势,它鼓励用IP核的方式进行设计.“IP Integrator”提供了原理图设计的方式,只需要在其中调用设计好的IP核连线.IP核一部分来自于Xilinx ...