【SAM manacher 倍增】bzoj3676: [Apio2014]回文串
做法一:PAM;做法二:SAM+manacher.前缀树上倍增
Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
【数据规模与评分】
数据满足1≤字符串长度≤300000。
题目分析
考虑暴力怎么做:首先对字符串$S$建立SAM,再使用manacher对所有$O(n)$级别的本质不同的回文子串查询出现个数。由于每次查询是$O(n)$的,所以暴力的复杂度是$O(n^2)$.
有一种SAM上计数的基本套路:在前缀树上倍增或是其他在树上的常规操作。对于这题则是考虑用倍增快速查询$S(l,r)$在全串中的出现次数。
用$fa[i][j]$表示点$i$在前缀树上向上跳$2^j$步的父亲点数,那么从$p=id[r]$(即子串$S(1,r)$插入完毕的一部分SAM)开始查询,若$len[p]≥r-l+1$就说明点$p$所在的子树仍都是$S(l,r)$的后缀,因此一直向上跳直到不满足限制的点$p$的$size[p]$就是回文子串$S(l,r)$出现次数。
#include<bits/stdc++.h>
const int maxn = ; int n,g[maxn],lg2[maxn>>];
long long ans;
int size[maxn],dep[maxn],id[maxn],sta[maxn];
int cnt[maxn],pos[maxn];
char s[maxn],t[maxn];
struct SAM
{
int lst,tot;
int fa[maxn][],len[maxn];
std::map<int, int> ch[maxn]; //似乎略卡空间
SAM(){lst = tot = ;}
void extend(int c, int id)
{
int p = lst, np = ++tot;
lst = np, len[np] = len[p]+, sta[id] = np; //sta[np]=id
for (; p&&!ch[p][c]; p=fa[p][]) ch[p][c] = np;
if (!p) fa[np][] = ;
else{
int q = ch[p][c];
if (len[q]==len[p]+) fa[np][] = q;
else{
int nq = ++tot;
len[nq] = len[p]+, ch[nq] = ch[q];
fa[nq][] = fa[q][], fa[q][] = fa[np][] = nq;
for (; ch[p][c]==q; p=fa[p][]) ch[p][c] = nq;
}
}
size[np] = ;
}
void build()
{
for (int i=; i<=tot; i++) ++cnt[len[i]];
for (int i=; i<=tot; i++) cnt[i] += cnt[i-];
for (int i=tot; i>=; i--) pos[cnt[len[i]]--] = i;
for (int i=tot; i>=; i--)
size[fa[pos[i]][]] += size[pos[i]];
for (int i=; i<=tot; i++)
{
int p = pos[i];
dep[p] = dep[fa[p][]]+;
for (int j=; j<=; j++)
fa[i][j] = fa[fa[i][j-]][j-];
}
}
void match(int l, int r)
{
if (l > r||l < ||r > n) return;
int p = sta[r];
for (int i=lg2[dep[p]]; i>=; i--)
{
int fat = fa[p][i];
if (len[fat] >= r-l+) p = fat;
}
ans = std::max(ans, 1ll*size[p]*(r-l+));
}
}f; void manacher()
{
int m = , mid = ;
t[] = '!', t[++m] = '@';
for (int i=; i<=n; i++)
t[++m] = s[i], id[m] = i, t[++m] = '@';
for (int i=, mx=-; i<m; i++)
{
if (i >= mx) g[i] = ;
else g[i] = std::min(mx-i, g[*mid-i]);
f.match(id[i-g[i]+], id[i+g[i]-]);
for (; t[i-g[i]]==t[i+g[i]]; )
++g[i], f.match(id[i-g[i]+], id[i+g[i]-]); //id[i-g[i]], id[i+g[i]]
if (i+g[i] > mx) mx = i+g[i], mid = i;
}
}
int main()
{
scanf("%s",s+);
n = strlen(s+);
for (int i=; i<=n; i++)
f.extend(s[i]-'a', i), lg2[i] = i>?(lg2[i>>]+):;
f.build();
manacher();
printf("%lld\n",ans);
return ;
}
END
【SAM manacher 倍增】bzoj3676: [Apio2014]回文串的更多相关文章
- bzoj3676 [Apio2014]回文串 卡常+SAM+树上倍增
bzoj3676 [Apio2014]回文串 SAM+树上倍增 链接 bzoj luogu 思路 根据manacher可以知道,每次暴力扩展才有可能出现新的回文串. 所以推出本质不同的回文串个数是O( ...
- [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串
回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...
- [BZOJ3676][APIO2014]回文串(Manacher+SAM)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 3097 Solved: 1408[Submit][Statu ...
- [Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 3396 Solved: 1568[Submit][Statu ...
- [bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增
Brief Description 一个回文串的value定义为这个回文串的长度乘以出现次数.给定一个字符串,求\(value_{max}\). Algorithm Design 我们使用Manach ...
- BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)
Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行 ...
- BZOJ3676 APIO2014回文串(manacher+后缀自动机)
由于本质不同的回文子串数量是O(n)的,考虑在对于每个回文子串在第一次找到它时对其暴力统计.可以发现manacher时若右端点移动则找到了一个新回文串.注意这样会漏掉串长为1的情况,特判一下. 现在问 ...
- BZOJ3676 APIO2014 回文串 Manacher、SA
传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...
- 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)
传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...
- 【回文自动机】bzoj3676 [Apio2014]回文串
回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i ...
随机推荐
- 使用工具自动生成Linq类文件
第一部:运行cmd. 执行命令 cd C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools 第二步:执行 ...
- jQuery树形控件zTree使用
http://www.cnblogs.com/AutumnRhyme/p/5915769.html .................................................. ...
- Bonetrousle HackerRank 数学 + 思维题
https://www.hackerrank.com/contests/world-codesprint-6/challenges/bonetrousle 给定一个数n,和k个数,1--k这k个,要求 ...
- Abbreviation ---- hackerrank
---恢复内容开始--- https://www.hackerrank.com/contests/world-codesprint-6/challenges/abbr 给定两个串str和sub. 对于 ...
- redis数据类型--个人常规用法
一.String 1.可以容纳最高512M的value. 2.经常用于通过expire来实现自动过期的一些值,直接通过setex 来. 3.通过incrby的方式,来实现value值得增长. 4.执行 ...
- HTTPS和SSL证书
1. HTTPS工作原理 HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,(目的是安全的获得对称密钥用户后续传输加密)过程的简单描述如下: a).浏览器讲自己支持的多个加 ...
- awk 分解行、字段
1. 格式 格式: awk 'pattern {action} pattern {action}' filename 注:多个文件时,读取从左到右,读完第一个再读取第二个 pattern 1-/正则表 ...
- cucumber的疑问解答
在cucumber的自动化测试框架下面,在一个steps文件中定义的@page对象,可以在其他的不同的steps文件中调用,在整个的场景生命周期中都是有效的 原因:cucumber开始执行时,一次性把 ...
- 【转】sql server数据库操作大全——常用语句/技巧集锦/经典语句
本文为累计整理,有点乱,凑合着看吧! ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ ☆ ☆ ☆ sql 宝 典 ☆ ☆ ☆ 2012年-8月 修订版 ☆ ...
- Android图表库XCL-Charts
首先,这个是国人开发的,支持下必须顶!github项目地址:点击打开,由于项目的基本功能已经实现,所以项目作者也说以后基本不会在有更新了. 项目简介: Android图表库(XCL-Charts is ...