[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 ...
随机推荐
- Hibernate 多表查询 - Criteria添加子字段查询条件 - 出错问题解决
Criteria 查询条件如果是子对象中的非主键字段会报 could not resolve property private Criteria getCriteria(Favorite favori ...
- 学习C语言库函数
使用C语言功能强大的函数,我们需要包含头文件 #include<math.h>. 1)取两个数的较大值或较小值函数: double a = 9.9; double b = 6.6; pri ...
- [图文][提供可行性脚本] CentOS 7 Fencing+Pacemaker三节点搭建高可用集群
实验说明: 实验环境: 宿主机系统 :Fedora 28 WorkStation 虚拟机管理器 :Virt-Manager 1.5.1 虚拟机配置 :ha1 CentOS 7.2 1511 ...
- 解析Java finally
以下用几个简单的例子介绍一下finally的用法: 例子1 public class Test { public static void main(String[] args) { System.ou ...
- clock gate
clock gate 这个专题,比较复杂设计DC PT PR.下面仅仅从RTL行为级说明一下.
- tomcat 修改默认端口8080 为 80端口
首先,找到你的安装目录,如图: 打开server.xml文件,找到8080,如图: 将 8080 改成你想要的端口,如 80 即可.改完后,记得要重启tomcat! 将端口改成 80 后,访问就不需 ...
- Python 日期与时间
Python 3.6.4 import time, calendar, datetime print("距离1970年的秒数为:", time.time()) print(&quo ...
- numpy hstack()
numpy.hstack(tup)[source] Stack arrays in sequence horizontally (column wise). Take a sequence of ar ...
- 九度oj 题目1135:字符串排序
题目描述: 先输入你要输入的字符串的个数.然后换行输入该组字符串.每个字符串以回车结束,每个字符串少于一百个字符. 如果在输入过程中输入的一个字符串为“stop”,也结束输入. 然后将这输入的该组字符 ...
- 注册苹果开发者账号和iOS9打包上线
链接: http://www.jianshu.com/p/507ca4e5fde0 http://blog.csdn.net/a283127993/article/details/45828175 i ...