做法一: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]回文串的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)

    Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行 ...

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

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

  8. BZOJ3676 APIO2014 回文串 Manacher、SA

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

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

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

  10. 【回文自动机】bzoj3676 [Apio2014]回文串

    回文自动机讲解!http://blog.csdn.net/u013368721/article/details/42100363 pam上每个点代表本质不同的回文子串.len(i)代表长度,cnt(i ...

随机推荐

  1. 05-树9 Huffman Codes (30 分)

    In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redunda ...

  2. matplotlib 知识点11:绘制饼图(pie 函数精讲)

    饼图英文学名为Sector Graph,又名Pie Graph.常用于统计学模块. 画饼图用到的方法为:matplotlib.pyplot.pie( ) #!/usr/bin/env python # ...

  3. 高并发web系统优化总结

    1.背景 因为业务需要,搭建了一个系统,系统主要由两部分组成,web页面和数据库. mysql大概2万条数据,其中有一个字段是click_num点击次数,php页面会取点击次数最小的一条记录去进行操作 ...

  4. QT学习小demo之LightMD(MarkDown编辑器)

    很早之前就有了写一个类似Windows记事本的想法,加上最近也刚好在学编译原理,所以就想把两者结合起来,于是就打算结合MarkDown,开发一款MarkDown编辑器. 不过由于我之前一直使用的是Ja ...

  5. phpize使用方法

    phpize是用来扩展php扩展模块的,通过phpize可以建立php的外挂模块,下面介绍一个它的使用方法,需要的朋友可以参考下 安装(fastcgi模式)的时候,常常有这样一句命令: 代码如下: / ...

  6. mysql报错this is incompatible with sql_mode=only_full_group_by

    1.报错信息 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: In aggregated query without GROUP ...

  7. linux下的idea的界面问题,错位以及各种...

    问题 ’ 方法 主题设置为GTK,多余的点会消失,而且字体也会好很多

  8. linux cached过高导致性能变低

    场景: 拿到了客户50个文件,平均每个文件大概40M左右的txt,文件在S3上,需要导入到数据库,40M解析出来大概是80W条左右的数据. 描述: 在刚开始执行导入时,因为数据验证复杂程度不同,每个文 ...

  9. java 基础 02 数据类型、运算符、分支结构

    内容: (1)数据类型 (2)运算符 (3)分支结构 1.数据类型 java语言中的基本数据类型:byte.short.int.long.float.double.boolean.char. 1.1布 ...

  10. Web框架的应用

    从今天开始,我们将要学习有关Web框架的一些内容,在学习之前先来学习一下http协议,即基于http是如何通信的. http 概要:http是基于tcp/ip通信协议来传输数据的. 优点: 1.简单快 ...