题面:洛谷

题解:

  还是这个性质:对于每个串而言,本质不同的回文串最多只有O(n)个。

  所以我们先求出这O(n)个本质不同的回文串,然后对整个串求一次sa。

  然后对于每个回文串,求出它的出现次数,更新答案即可。

  如何用后缀数组求一个串的出现次数?

  因为每个串都必然是某个后缀的前缀。因此我们先找到这个串x,然后在周围二分,寻找一个最大的区间[l, r]使得区间内每个串与x的LCP都大于等于这个串的长度。

  可以证明,这样的区间必然是连续的一个。

  因此在周围分别向上向下二分一下最多能延伸到哪,是否可行用st表维护一下height数组的最小值即可O(1)查询LCP大小。

  

 // luogu-judger-enable-o2
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 601000
#define ac 601000
#define LL long long int n, m = , pos, maxn;
LL ans;
int r[ac], sa[AC], rk[AC], p1[AC], p2[AC], b[AC], d[AC];//第几是谁,你是第几, 两个关键字,临时数组,桶
int st[AC][], h[AC], last[AC], length[AC];
char ss[AC], s[ac];//原串,扩充串 inline void upmax(LL &a, LL b){
if(b > a) a = b;
} void pre()
{
scanf("%s", ss + ), n = strlen(ss + );
s[] = '$', s[] = '#';
for(R i = ; i <= n; i ++) s[i << ] = ss[i], s[(i << ) + ] = '#';//manacher数组
for(R i = ; i <= n; i ++) sa[i] = i, rk[i] = ss[i];//初始化后缀数组
} void ssort()
{
for(R i = ; i <= n; i ++) ++ d[p2[i]];
for(R i = ; i <= m; i ++) d[i] += d[i - ];
for(R i = ; i <= n; i ++) b[d[p2[i]] --] = i;//给i分配排名(临时sa数组)
for(R i = ; i <= m; i ++) d[i] = ; for(R i = ; i <= n; i ++) ++ d[p1[i]];
for(R i = ; i <= m; i ++) d[i] += d[i - ];
for(R i = n; i; i --) sa[d[p1[b[i]]] --] = b[i];//依次给b[i]分配排名
for(R i = ; i <= m; i ++) d[i] = ;
} void sa_sort()
{
for(R k = ; k <= n; k <<= )
{
for(R i = ; i <= n; i ++)
p1[i] = rk[i], p2[i] = rk[i + k];
ssort();
int tmp = ;
rk[sa[]] = ;
for(R i = ; i <= n; i ++)
rk[sa[i]] = (p1[sa[i]] == p1[sa[i - ]] && p2[sa[i]] == p2[sa[i - ]]) ? tmp : ++ tmp;
if(tmp >= n) break;
m = tmp;
}
} void manacher()//获取回文串
{
int b = * n;
for(R i = ; i <= b; i ++)
{
r[i] = (maxn > i) ? min(r[(pos << ) - i], maxn - i + ) : ;
while(s[i - r[i]] == s[i + r[i]]) ++ r[i];
int t = i + r[i] - ;
if(t > maxn)
{
for(R j = maxn + ; j <= t; ++ j)
{
last[j] = (i << ) - j;//串的开始是要算的,,,,
if(s[j] == '#') continue;
length[j] = ((j - last[j]) >> ) + ;
}
pos = i, maxn = t;
}
} /*for(R i = 1; i <= b; i ++)
{
if(s[i] == '#') continue;
length[i] = ((i - last[i]) >> 1) + 1;//(r - l) / 2 + 1算出字母的长度(个数)
}*/
} void build()//求height数组
{
//h[sa[1]] = 0;
for(R i = , k = ; i <= n; i ++)//按照原串顺序求h
{
if(k) -- k;//将k变为上一次的h[i] - 1
int j = sa[rk[i] - ];
while(ss[i + k] == ss[j + k] && k <= n) ++ k;
h[rk[i]] = k;
}
} int t1[AC], t2[AC];//最接近i的2的n次幂的指数,对应的大小 void get_st()
{
int tt = , tmp = ;
for(R i = ; i <= n; i ++)
{
st[i][] = h[i];
if(i == (tmp << )) tmp <<= , ++ tt;
t1[i] = tt, t2[i] = tmp;
}
tmp = ;
for(R i = ; i <= ; i ++)
{
for(R j = ; j <= n; j ++)
st[j][i] = min(st[j][i - ], st[j + tmp][i - ]);
tmp <<= ;
}
} bool check(int l, int r, int lim)//看min[l, r]是否>= lim
{
int rnt = , len = (r - l + );
rnt = min(st[l][t1[len]], st[r - t2[len] + ][t1[len]]);
return rnt >= lim;
} LL half(int x, int len)//获取出现次数
{
int l = , r = x;
while(l < r)//查找前一段里面第一个符合的
{
int mid = (l + r) >> ;
if(check(mid + , x, len)) r = mid;
else l = mid + ;
}
int ll = l;//记录左边界
l = x, r = n;
while(l < r)//查找后一段里面最后一个符合的
{
int mid = (l + r + ) >> ;
if(check(x + , mid, len)) l = mid;
else r = mid - ;
}
return r - ll + ;
} void work()
{
int b = * n;
for(R i = ; i <= b; i ++)
{
if(s[i] == '#') continue;
upmax(ans, 1LL * length[i] * half(rk[last[i] >> ], length[i]));
}
printf("%lld\n", ans);
} int main()
{
// freopen("in.in", "r", stdin);
pre();
sa_sort();
build();
get_st();
manacher();
work();
// fclose(stdin);
return ;
}

[APIO2014]回文串 manacher 后缀数组的更多相关文章

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

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

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

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

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

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

  4. BZOJ4755 [JSOI2016]扭动的回文串 【后缀数组】【manacher】

    题目分析: 我写了史上最丑的后缀数组,怎么办? 首先manacher一遍两个串,这样只用考虑第三问.用$作为间隔符拼接两个串,把第一个串翻转.枚举回文中心,取最长的回文串,对于剩下的部分利用LCP匹配 ...

  5. BZOJ3676 APIO2014 回文串 Manacher、SA

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

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

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

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

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

  8. 【BZOJ 3676】 3676: [Apio2014]回文串 (SAM+Manacher+倍增)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2343  Solved: 1031 Description 考 ...

  9. BZOJ 3676: [Apio2014]回文串

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2013  Solved: 863[Submit][Status ...

随机推荐

  1. 源码阅读-GlobalTimer

    最近看到一篇文章推了一个开源项目,GlobalTimer.主要是可以用一个定时器来统一管理多个定时任务,可以针对特定任务进行管理. 一.原理 1.一个公共的timer 2.封装任务到自定义个Event ...

  2. PHP5.4 连接 SQL SERVER 2008

    PHP链接sqlserver需要先安装驱动,不是先把dll放到ext下面,一重启服务器就完事了. 本地环境: XAMPP 1.8.2 PHP 5.4.31 SQL SERVER 2008 R2 使用的 ...

  3. 洛谷P1514 引水入城

    洛谷P1514 引水入城 原题链接 一道好题...细节真多 第一次提交90分,然后就GG了,不知从何改起 其实比较简单吧... 首先,一个点的水流向最后一排,一定可以形成一个区间. 不行的话肯定GG ...

  4. 解决 idea template jsp模板中使用自定义路径 模板不显示问题

    ${} 是一个模板中的关键字,所以建立时需要用 \ 注释即可正常显示  ${APP_PATH}

  5. NTP(Network Time Protocol)

    Linux NTP配置详解 (Network Time Protocol) http://www.ntp.org/ Meinberg NTP packages provide a GUI instal ...

  6. centos下JDK安装及环境变量配置

    由于centos安装自带openjdk,需要将其卸载后安装自己的jdk 卸载centos自带jdk 1.查找java :rpm -qa | grep java 2.卸载时提示权限不够,进入root目录 ...

  7. 2018百度之星开发者大赛-paddlepaddle学习

    前言 本次比赛赛题是进行人流密度的估计,因为之前看过很多人体姿态估计和目标检测的论文,隐约感觉到可以用到这次比赛上来,所以趁着现在时间比较多,赶紧报名参加了一下比赛,比赛规定用paddlepaddle ...

  8. Phaser游戏框架与HTML Dom元素之间的通信交互

    本想按照PHASER的HTML Dom元素官方实例:http://labs.phaser.io/index.html?dir=game%20objects/dom%20element/&q=  ...

  9. PHP核心技术——魔术方法

    魔术方法: 魔术方法是以两个下画线开头.具有特殊作用的一些方法,可以看做PHP的"语法糖". set和get方法: class Account{ private $user=1; ...

  10. 136.只出现一次的数字 leetcode ^运算符 JavaScript解法

    leetcode上的一道题简单题 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间 ...