[bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增
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+后缀自动机+倍增的更多相关文章
- [Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 3396 Solved: 1568[Submit][Statu ...
- 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)
传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...
- [BZOJ3676][APIO2014]回文串(Manacher+SAM)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 3097 Solved: 1408[Submit][Statu ...
- BZOJ3676 APIO2014 回文串 Manacher、SA
传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...
- [APIO2014]回文串 manacher 后缀数组
题面:洛谷 题解: 还是这个性质:对于每个串而言,本质不同的回文串最多只有O(n)个. 所以我们先求出这O(n)个本质不同的回文串,然后对整个串求一次sa. 然后对于每个回文串,求出它的出现次数,更新 ...
- bzoj 3676: [Apio2014]回文串【后缀自动机+manacher】
用manacher找出本质不同的回文子串放在SAM上跑 #include<iostream> #include<cstdio> #include<cstring> ...
- [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串
回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...
- bzoj3676 [Apio2014]回文串 卡常+SAM+树上倍增
bzoj3676 [Apio2014]回文串 SAM+树上倍增 链接 bzoj luogu 思路 根据manacher可以知道,每次暴力扩展才有可能出现新的回文串. 所以推出本质不同的回文串个数是O( ...
- BZOJ3676 APIO2014回文串(manacher+后缀自动机)
由于本质不同的回文子串数量是O(n)的,考虑在对于每个回文子串在第一次找到它时对其暴力统计.可以发现manacher时若右端点移动则找到了一个新回文串.注意这样会漏掉串长为1的情况,特判一下. 现在问 ...
随机推荐
- SQL On Streaming
此文已由作者岳猛授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 实时计算的一个方向 实时计算未来会成为一个趋势,基本上所有的离线计算任务都能通过实时计算来完成,对于实时计算来 ...
- 修改npm全局安装模式的路径
由于npm全局模块的存放路径及cache的路径默认是放在C盘下,这样肯定会增加C盘的负担,那么如果需要修改其存放路径应该怎么做呢? 第一步:在nodejs安装目录(也可以指定其它目录)下创建”node ...
- JavaScript RegExp 身份证、账号密码、email正则
什么是正则表达式 正则表达式是构成搜索模式. 在文本中搜索数据时,可以使用此搜索模式来描述正在搜索的内容. 正则表达式可以是单个字符,也可以是更复杂的模式. 正则表达式可用于执行所有类型的文本搜索和文 ...
- 数据挖掘算法:k-means算法的C++实现
(期末考试要到了,所以比较粗糙,请各位读者理解..) 一. 概念 k-means是基于原型的.划分的聚类技术.它试图发现用户指定个数(K)的簇(由质心代表).K-means算法接受输入量K,然后 ...
- 在 C/C++ 中使用 TensorFlow 预训练好的模型—— 直接调用 C++ 接口实现
现在的深度学习框架一般都是基于 Python 来实现,构建.训练.保存和调用模型都可以很容易地在 Python 下完成.但有时候,我们在实际应用这些模型的时候可能需要在其他编程语言下进行,本文将通过直 ...
- css制作环形文本
css制作环形文本 在项目开发中,我们可能会遇到环形文本的需求,这个时候,怎样在代码以通俗易懂的前提下实现我们需要的效果呢?可能你会想到用一个一个的span元素计算出旋转的角度然后拼接起来,这个方案不 ...
- 团队项目-第十次scrum 会议
时间:11.6 时长:20分钟 地点:主235教室走廊 工作情况 团队成员 已完成任务 待完成任务 解小锐 完成多种招聘方式的逻辑编写 陈鑫 实现游戏的存档功能 李金奇 添加多种招聘方式等功能 王辰昱 ...
- PAT 1040 有几个PAT
https://pintia.cn/problem-sets/994805260223102976/problems/994805282389999616 字符串 APPAPT 中包含了两个单词 PA ...
- 使用 Redis的SETNX命令实现分布式锁
使用Redis的 SETNX 命令可以实现分布式锁,下文介绍其实现方法. SETNX命令简介 命令格式 SETNX key value 将 key 的值设为 value,当且仅当 key 不存在. 若 ...
- 'com.alibaba.fastjson.support.spring.FastJsonpResponseBodyAdvice' is。。。。
com.alibaba.fastjson版本1.2.43版本在通过xml方式配置spring的时候会出现这个个奇怪的问题: Class 'com.alibaba.fastjson.support.sp ...