[Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)
3676: [Apio2014]回文串
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 3396 Solved: 1568
[Submit][Status][Discuss]
Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
Sample Input
abacaba
【样例输入2]
www
Sample Output
【样例输出2]
HINT
一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。
在第一个样例中,回文子串有7个:a,b,c,aba,aca,bacab,abacaba,其中:
● a出现4次,其出现值为4:1:1=4
● b出现2次,其出现值为2:1:1=2
● c出现1次,其出现值为l:1:l=l
● aba出现2次,其出现值为2:1:3=6
● aca出现1次,其出现值为1=1:3=3
●bacab出现1次,其出现值为1:1:5=5
● abacaba出现1次,其出现值为1:1:7=7
故最大回文子串出现值为7。
【数据规模与评分】
数据满足1≤字符串长度≤300000。
分析:
回文树眼题,但是我不会回文树QAQ
AC代码:
# include <iostream>
# include <cstdio>
# include <cstring>
using namespace std;
const int N = 3e5 + ;
long long ans;
int ch[N << ][];
int dis[N << ],fa[N << ],w[N << ],cnt = ,len;
int que[N << ],p[N << ],dt,Log[],g[N << ][],Id[N];
char str[N],s[N << ];
int Sam(int c,int last)
{
int u = last,cur;
while(u && !ch[u][c])que[++que[]] = u,u = fa[u];
if(!u)
{
cur = ++cnt;fa[cur] = ;
while(que[])ch[que[que[]--]][c] = cur;
}
else
{
int v = ch[u][c];
if(dis[v] == dis[u] + )
{
cur = ++cnt;fa[cur] = v;
while(que[])ch[que[que[]--]][c] = cur;
}
else
{
int av = ++cnt;dis[av] = dis[u] + ;cur = ++cnt;
while(que[])ch[que[que[]--]][c] = cur;
memcpy(ch[av],ch[v],sizeof ch[v]);
fa[av] = fa[v];fa[v] = fa[cur] = av;
while(u && ch[u][c] == v)ch[u][c] = av,u = fa[u];
}
}
dis[cur] = dis[last] + ;
return cur;
}
void Manacher()
{
s[] = '$';s[dt = ] = '#';
for(int i = ;i <= len;i++)s[++dt] = str[i],s[++dt] = '#';
int mx = ,id = ;p[] = p[] = ;
for(int i = ;i < dt;i++)
{
p[i] = min(p[ * id - i],mx - i);
while(s[i + p[i] + ] == s[i - p[i] - ])
{
p[i]++;
if((i + p[i]) & )
{
int now = Id[(i + p[i] - ) >> ],L = ((i + p[i] - ) >> ) - ((i - p[i] + ) >> ) + ;
for(int j = ;~j;j--)if(dis[g[now][j]] >= L)now = g[now][j];
ans = max(ans,1LL * L * w[now]);
}
}
if(i + p[i] > mx)
{
id = i;
mx = i + p[i];
}
}
}
void init()
{
Log[] = ;for(int i = ;i < ;i++)Log[i] = Log[i - ] << ;
for(int i = ;i <= cnt;i++)g[i][] = fa[i];//这里考场上写成了<=len,结果得了90
for(int j = ;j <= ;j++)
for(int i = ;i <= cnt;i++)
g[i][j] = g[g[i][j - ]][j - ];
}
int main()
{
scanf("%s",str + );len = strlen(str + );Id[] = ;
for(int i = ;i <= len;i++)Id[i] = Sam(str[i] - 'a',Id[i - ]),w[Id[i]]++;
for(int i = ;i <= cnt;i++)p[dis[i]]++;
for(int i = ;i <= len;i++)p[i] += p[i - ];
for(int i = cnt;i >= ;i--)que[p[dis[i]]--] = i;
for(int i = cnt;i >= ;i--)w[fa[que[i]]] += w[que[i]];
init();Manacher();
printf("%lld\n",ans);
return ;
}
[Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)的更多相关文章
- bzoj3676 [Apio2014]回文串 卡常+SAM+树上倍增
bzoj3676 [Apio2014]回文串 SAM+树上倍增 链接 bzoj luogu 思路 根据manacher可以知道,每次暴力扩展才有可能出现新的回文串. 所以推出本质不同的回文串个数是O( ...
- BZOJ 3676 [Apio2014]回文串 (后缀自动机+manacher/回文自动机)
题目大意: 给你一个字符串,求其中回文子串的长度*出现次数的最大值 明明是PAM裸题我干嘛要用SAM做 回文子串有一个神奇的性质,一个字符串本质不同的回文子串个数是$O(n)$级别的 用$manach ...
- BZOJ 3676: [Apio2014]回文串 后缀自动机 Manacher 倍增
http://www.lydsy.com/JudgeOnline/problem.php?id=3676 过程很艰难了,第一次提交Manacher忘了更新p数组,超时,第二次是倍增的第0维直接在自动机 ...
- [APIO2014]回文串 后缀自动机_Manancher_倍增
Code: // luogu-judger-enable-o2 #include <cstdio> #include <algorithm> #include <cstr ...
- [模板] 回文树/回文自动机 && 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回文串(manacher+后缀自动机)
由于本质不同的回文子串数量是O(n)的,考虑在对于每个回文子串在第一次找到它时对其暴力统计.可以发现manacher时若右端点移动则找到了一个新回文串.注意这样会漏掉串长为1的情况,特判一下. 现在问 ...
- 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)
传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...
- [bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增
Brief Description 一个回文串的value定义为这个回文串的长度乘以出现次数.给定一个字符串,求\(value_{max}\). Algorithm Design 我们使用Manach ...
随机推荐
- Java中的线程--多线程面试题
到这里,基本上线程的并发中的知识点都是学到了,到了最后,还有三道面试题,从面试题中学习更加的加深一下,多线程中的知识点,如何在实际的问题中来解决多线程的问题,可以更好的从实际出发 一.面试题1 面试题 ...
- Linux 永久修改主机名hostname
前言: 由于最近用3台机器,经常切换导致有容易区别的需求. 故想修改主机名. 实验环境:Ubuntu 17 教程: 1. 使用hostname 命令先临时修改 sudo hostname your_n ...
- break、continue、exit、return的区别和对比
break.continue.exit.return的区别和对比 一:说明 break.continue在条件循环语句及循环语句(for.while.if等)中用于控制程序的走向:而exit则用于种植 ...
- RN原生的安卓UI组件
https://facebook.github.io/react-native/docs/native-components-android.html 这里有一大堆的原生组件可以用,一些是平台自带的, ...
- perl学习之:肯定匹配和否定匹配
tr/ / / 替换操作符不支持正则表达式 也不具备双引号替换能力m/ / s/ / / 都支持正则表达式,并且可以提供或限制双引号替换能力 $string = "25abc8" ...
- cs229_part5
这部分主要补充一些cs229没涉及到,但是实际上非常重要,而且是实际中真正会用的一些算法,即集成学习. 集成学习 问题背景 既然我们已经知道了很多学习算法,这些算法最终会输出一个结果.能不能把这些结果 ...
- Linux下平滑升级nginx
一.升级前准备 1.对nginx的配置文件nginx.conf做备份: 2.新建目录/root/nginx,将安装包和脚本上传到该目录下: 二.平滑升级nginx 1.开始编译新版本的nginx cd ...
- 使用systemctl命令管理服务mysql
启动mysql systemctl start mysqld.service 停止mysql systemctl stop mysqld.service 重启mysql systemctl resta ...
- Title共通写法
用: <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_c ...
- iOS第三方地图-高德地图(导航sdk路径规划)
@import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...