Brief Description

一个回文串的value定义为这个回文串的长度乘以出现次数。给定一个字符串,求\(value_{max}\)。

Algorithm Design

我们使用Manacher暴力算出所有的回文子串,放在SAM里倍增,大力算贡献就好了。

Code

#include <algorithm>
#include <cstdio>
#define ll long long
#include <cstring>
const int maxn = 600010;
int n;
ll ans;
int p[maxn];
char str[maxn];
struct Suffix_Automaton {
int trans[maxn][26], fa[maxn][20], pos[maxn], len[maxn], size[maxn];
int last, root, sz;
int v[maxn], q[maxn], dep[maxn];
void init() {
sz = 0;
last = root = ++sz;
}
void insert(int x, int id) {
int p = last, np = last = ++sz;
len[np] = len[p] + 1;
pos[id] = np;
size[np] = 1;
for (; !trans[p][x]; p = fa[p][0])
trans[p][x] = np;
if (p == 0)
fa[np][0] = root;
else {
int q = trans[p][x];
if (len[q] == len[p] + 1) {
fa[np][0] = q;
} else {
int nq = ++sz;
for (int i = 0; i < 26; i++)
trans[nq][i] = trans[q][i];
fa[nq][0] = fa[q][0];
len[nq] = len[p] + 1;
fa[q][0] = fa[np][0] = nq;
for (; trans[p][x] == q; p = fa[p][0])
trans[p][x] = nq;
}
}
}
void pre() {
for (int i = 1; i <= sz; i++)
v[len[i]]++;
for (int i = 1; i <= n; i++)
v[i] += v[i - 1];
for (int i = sz; i >= 1; i--)
q[v[len[i]]--] = i;
for (int i = sz; i >= 1; i--) {
int t = q[i];
size[fa[t][0]] += size[t];
}
for (int i = 1; i <= sz; i++) {
int t = q[i];
dep[t] = dep[fa[t][0]] + 1;
for (int j = 1; (1 << j) <= dep[t]; j++)
fa[t][i] = fa[fa[t][i - 1]][i - 1];
}
}
void query(int l, int r) {
int ret = pos[r];
for (int i = 19; i >= 0; i--) {
int t = fa[ret][i];
if (len[t] >= r - l + 1)
ret = t;
}
ans = std::max(ans, (ll)size[ret] * (r - l + 1));
}
} sam;
void manacher() {
int mx = 1, id = 1;
for (int i = n; i; i--)
str[i * 2] = '#', str[i * 2 - 1] = str[i];
n <<= 1;
for (int i = 1; i <= n; i++) {
p[i] = std::min(p[id * 2 - i], mx - i);
while (i - p[i] > 0 && str[i - p[i]] == str[i + p[i]]) {
int al = (i - p[i]) / 2 + 1;
int ar = (i + p[i] + 1) / 2;
// printf("%d %d\n", al, ar);
sam.query(al, ar);
p[i]++;
}
if (i + p[i] > mx)
mx = i + p[i], id = i;
}
}
int main() {
#ifndef ONLINE_JUDGE
// freopen("input", "r", stdin);
#endif
scanf("%s", str + 1);
n = strlen(str + 1);
str[0] = '+', str[n + 1] = '-';
sam.init();
for (int i = 1; i <= n; i++) {
sam.insert(str[i] - 'a', i);
}
sam.pre();
manacher();
printf("%lld\n", ans);
}

[bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增的更多相关文章

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

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

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

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

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

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

  4. BZOJ3676 APIO2014 回文串 Manacher、SA

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

  5. [APIO2014]回文串 manacher 后缀数组

    题面:洛谷 题解: 还是这个性质:对于每个串而言,本质不同的回文串最多只有O(n)个. 所以我们先求出这O(n)个本质不同的回文串,然后对整个串求一次sa. 然后对于每个回文串,求出它的出现次数,更新 ...

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

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

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

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

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

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

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

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

随机推荐

  1. Linux 服务器 监控命令

    1 top top类似于windows下面的资源管理器.不仅能够从服务器整体上展示服务器的大致情况,还可以看到具体进程 耗费资源的情况. 展示内存.cpu.交换分区等信息 如上图: 第一行主要描述系统 ...

  2. 超强排序JavaScript插件

    Sortable:http://rubaxa.github.io/Sortable/

  3. 简单工具 & 杂技

    图片压缩: 腾讯智图(http://zhitu.isux.us/) 手机的所有尺寸大小规范: http://screensiz.es/phone 需求: 移动端宽高一致的盒子(因为移动端屏幕宽度不一样 ...

  4. Spring Cloud文档地址大全

    Spring Cloud:http://cloud.spring.io/spring-cloud-static/spring-cloud.html Spring Cloud Config:http:/ ...

  5. Python 并发编程:PoolExecutor 篇

    个人笔记,如有疏漏,还请指正. 使用多线程(threading)和多进程(multiprocessing)完成常规的并发需求,在启动的时候 start.join 等步骤不能省,复杂的需要还要用 1-2 ...

  6. URAL 1932 The Secret of Identifier(容斥)

    Description Davy Jones: You've been captain of the Black Pearl for 13 years. That was our agreement. ...

  7. 最小生成树(MST)

    原创 今天来说说最小生成树问题,我们知道最小生成树有两种求法,一种是prim算法,另一种是kruskal算法,关于两种算法的定义以及证明,请查看相关资料,这里不多说,理解起来也相当容易,我们来看一个问 ...

  8. 《学习OpenCV》课后习题解答9

    题目:(P126) 创建一个程序,使其读入并显示一幅图像.当用户鼠标点击图像时,获取图像对应像素的颜色值(BGR),并在图像上点击鼠标处用文本将颜色值显示出来. 解答: 本题关键是会用cvGet2D获 ...

  9. 【Autofac】- 创建的类的生命周期

    1.InstancePerDependency 对每一个依赖或每一次调用创建一个新的唯一的实例.这也是默认的创建实例的方式. 官方文档解释:Configure the component so tha ...

  10. union的代码有点难理解额

    union跟位域都可以节省内存,而且union在某些地方还能起到更好看的效果? 比如: struct Matrix { union { struct { float _f11, _f12, _f13, ...