#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. js 获取select的值 / js动态给select赋值

    jQuery获取Select选择的Text和Value:语法解释:1. $("#select_id").change(function(){//code...});   //为Se ...

  2. oracle聚合函数及行专列,pivot rollup cube

    1.原始数据 --方法-: --以单位分组,计算每类特殊情况的合计以及按照单位的小计数 with a as (SELECT b.szfz, case  when tsqk is not null th ...

  3. CRC校验和网络通信中writen、readn函数

    1.对网络传输的数据进行CRC32校验. #include <stdint.h> #include <stdio.h> #include <string.h> st ...

  4. Shell编程二

    告警系统需求分析 1.(虽然之前我们学习了zabbix,但有时候也不能满足我们的需求,比如比较冷门的监控项目需要写自定义脚本,或者服务器网络有问题,没有办法将客户端的数据发送到服务端.) 程序架构: ...

  5. Linux 基础学习(第二节)

    free命令用于显示当前系统中内存的使用量信息,格式为:“free [-h]”. 为了保证Linux系统不会突然卡住宕机,因此内存使用量应该是运维人员时刻要关注的数据啦,咱们可以使用-h参数来以更人性 ...

  6. 经典.net面试题目(转载)

    1. 简述 private. protected. public. internal 修饰符的访问权限. 答 . private :   私有成员, 在类的内部才可以访问. protected : 保 ...

  7. Laravel自定义分页样式

    <?php namespace App\Http\Controllers; use DB; use App\Http\Controllers\Controller; class UserCont ...

  8. Java并发编程(二):JAVA内存模型与同步规则

    一.Java内存模型(JMM) 它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式.一个线程如何和何时能看到其他线程共享变量的值,以及在 ...

  9. ATITIT.翻译模块的设计与实现 api attilax 总结

    ATITIT.翻译模块的设计与实现 api attilax 总结 1. 翻译原理1 2. TMX格式是国际通用格式(xml)1 2.1. 方法/步骤2 3. TRADOS2 4. ATITIT.翻译软 ...

  10. Java的ThreadContext类加载器的实现

    疑惑 以前在看源码的时候,总是会遇到框架里的代码使用Thread.currentThread.getContextClassLoader()获取当前线程的Context类加载器,通过这个Context ...