[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的情况,特判一下. 现在问 ...
随机推荐
- python简单的数据清洗,数据筛选方法归类
创建数组有两种方式,1.直接赋值 2.随机变量生成随机生成包括4种:np.arange(20),np.linspace(0,10,5),np.logspace(0,2,5),np.random.ran ...
- Android 序列化比对
本文转自:https://www.zybuluo.com/linux1s1s/note/91046 注:部分内容有更改 在Android中使用序列化,无非两种途经: Parcelable 和 Seri ...
- es6中类的注意事项
class Circle { constructor(radius) { this.radius = radius; Circle.circlesMade++; }; static draw(circ ...
- ES5新增数组方法(1):filter
检测数组元素,并返回符合条件所有元素的数组. 1.过滤数组中不符合条件的元素 let arr = [1, 2, 3, 4, 5, 6]; // 方式一 let newArr = arr.filter( ...
- 常用模块(chardet)
作用:检测二进制的编码格式,不是百分百正确 import chardet f = open('test.txt', 'rb')data = f.read()print(data)result = ch ...
- Daily Scrum02 11.30
纵然编译大作业压顶,大家还是顶住压力,保证了软工项目的持续进行. Member Today's Task Tomorrow's Task 李孟 Task856 熟悉单元测试方法熟悉单元测试方法 Tas ...
- 绝对定位后a、button等hover状态样式不显示问题
<div class="operate"> <el-button>提交项目</el-button> <el-button type=&qu ...
- 【题解】MUTC2013idiots
我是先知道的这题是FFT然后再做的,知道是FFT其实就是个套路题啦.首先,我们容易发现 \(P = \frac{a}{b}\) 其中a表示合法的方案数,而b表示全部的方案数. b的值即为\(C\lef ...
- [洛谷P4001][BJOI2006]狼抓兔子
题目大意:给你一个n*m的网格图,有三种边,横的,纵的和斜的,要你求出它的最小割 题解:网络流 卡点:1.无向图,反向弧容量应和正向弧相同 C++ Code: #include<cstdio&g ...
- CF#366 704D Captain America 上下界网络流
CF上的题,就不放链接了,打开太慢,直接上题面吧: 平面上有n个点, 第 i 个点的坐标为 ($X_i ,Y_i$), 你需要把每个点染成红色或者蓝色, 染成红色的花费为 r , 染成蓝色的花费为 b ...