【BZOJ 3676】 3676: [Apio2014]回文串 (SAM+Manacher+倍增)
3676: [Apio2014]回文串
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 2343 Solved: 1031Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
Sample Input
【样例输入l】
abacaba【样例输入2]
wwwSample Output
【样例输出l】
7【样例输出2]
4HINT
一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。
在第一个样例中,回文子串有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。
Source
【分析】
听说回文自动机可以秒掉这题,以后再学吧。
用串建SAM,然后求出right数组。
manacher告诉我们,本质不同的回文串最多n个,只有在mx变的时候可能增加一个回文串。
用manacher求出所有本质不同的回文串,然后在SAM上问。
那就是问[L,R]这个区间的子串出现了多少次【感觉这个用后缀数组的话是nlogn^2的
从SAM的pre边相当于AC自动机上的fail,形成一棵树,pre树上倍增即可。
就是从POS[R]开始跳,当他代表的子串的长度大于r-l+1,即可计入答案,当然子串长度越小越好(更有可能出现最多次)
【记得拓扑序
【啊。。。卡空间。。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 301000
#define LL long long // int mymax(int x,int y) {return x>y?x:y;}
LL mymax(LL x,LL y) {return x>y?x:y;}
int mymin(int x,int y) {return x<y?x:y;} LL ans=; struct node
{
int pre,step,son[],rt;
}t[*Maxn];int last,tot;
int v[*Maxn],q[*Maxn],pos[*Maxn]; int ff[*Maxn][];
void get_f()
{
for(int i=;i<=tot;i++) ff[i][]=t[i].pre;
for(int i=;i<=tot;i++)
{
int nw=q[i];
for(int j=;j<=;j++)
ff[nw][j]=ff[ff[nw][j-]][j-];
}
} int now;
struct sam
{
void extend(int k)
{
int np=++tot,p=last;
t[np].step=t[last].step+;
t[np].rt=;pos[++now]=np;
while(p&&!t[p].son[k])
{
t[p].son[k]=np;
p=t[p].pre;
}
if(!p) t[np].pre=;
else
{
int q=t[p].son[k];
if(t[q].step==t[p].step+) t[np].pre=q;
else
{
int nq=++tot;
memcpy(t[nq].son,t[q].son,sizeof(t[nq].son));
t[nq].step=t[p].step+;
t[nq].pre=t[q].pre;
t[q].pre=t[np].pre=nq;
while(p&&t[p].son[k]==q)
{
t[p].son[k]=nq;
p=t[p].pre;
}
}
}
last=np;
}
void init()
{
memset(v,,sizeof(v));
for(int i=;i<=tot;i++) v[t[i].step]++;
for(int i=;i<=tot;i++) v[i]+=v[i-];
for(int i=tot;i>=;i--) q[v[t[i].step]--]=i; for(int i=tot;i>=;i--)
{
int nw=q[i];
t[t[nw].pre].rt+=t[nw].rt;
}
}
void ffind(int l,int r)
{
l=l/+;r=(r+)/;
int x=pos[r];
for(int i=;i>=;i--)
{
if(t[ff[x][i]].step>=r-l+) x=ff[x][i];
}
ans=mymax(ans,1LL*(r-l+)*t[x].rt);
}
}sam; char s[Maxn];
// int a[2*Maxn],p[2*Maxn]; void manacher(int l)
{
v[]=;
for(int i=;i<l;i++) v[*i+]=s[i]-'a'+,v[*i+]=;
v[*l+]=;
l=*l;
int mx=,id=;
for(int i=;i<=l;i++)
{
if(i<mx) q[i]=mymin(mx-i+,q[*id-i]);
else q[i]=;
while(v[i+q[i]]==v[i-q[i]]&&i-q[i]>=)
{
q[i]++;
sam.ffind(i-q[i]+,i+q[i]-);
}
if(i+q[i]->mx) mx=i+q[i]-,id=i;
}
} int main()
{
scanf("%s",s);
int l=strlen(s);
last=tot=;now=;
for(int i=;i<l;i++) sam.extend(s[i]-'a'+);
sam.init();
get_f();
manacher(l);
printf("%lld\n",ans);
return ;
}
2017-04-17 16:54:09
【BZOJ 3676】 3676: [Apio2014]回文串 (SAM+Manacher+倍增)的更多相关文章
- BZOJ3676:[APIO2014]回文串(SAM,Manacher)
Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行 ...
- BZOJ3676 APIO2014回文串(manacher+后缀自动机)
由于本质不同的回文子串数量是O(n)的,考虑在对于每个回文子串在第一次找到它时对其暴力统计.可以发现manacher时若右端点移动则找到了一个新回文串.注意这样会漏掉串长为1的情况,特判一下. 现在问 ...
- bzoj 3676 [Apio2014]回文串(Manacher+SAM)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3676 [题意] 给定一个字符串,定义一个串的权值为长度*出现次数,求最大权的回文子串. ...
- 【BZOJ 3676】[Apio2014]回文串
[链接] 链接 [题意] 给你一个字符串s. 定义一个子串的出现值为它出现的次数*字符串的长度. 让你求里面的回文子串的最大出现值 |s|<=3e5 [题解] 马拉车算法里面. 只有在回文往外扩 ...
- bzoj3676 [Apio2014]回文串 卡常+SAM+树上倍增
bzoj3676 [Apio2014]回文串 SAM+树上倍增 链接 bzoj luogu 思路 根据manacher可以知道,每次暴力扩展才有可能出现新的回文串. 所以推出本质不同的回文串个数是O( ...
- BZOJ 3676: [Apio2014]回文串
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2013 Solved: 863[Submit][Status ...
- bzoj 3676: [Apio2014]回文串 回文自动机
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 844 Solved: 331[Submit][Status] ...
- 3676: [Apio2014]回文串
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 1740 Solved: 744 [Submit][Status ...
- 3676: [Apio2014]回文串 求回文串长度与出现次数的最大值
「BZOJ3676」[Apio2014] 回文串 Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所 ...
随机推荐
- ⑦ 设计模式的艺术-13.代理(Proxy)模式
为什么需要代理模式 中介隔离作用:在某些情况下,一个客户类不想或者不能直接引用一个委托对象,而代理类对象可以在客户类和委托对象之间起到中介的作用,其特征是代理类和委托类实现相同的接口. 开闭原则,增加 ...
- centOS7 vsftp ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf (code=exited, status=0/SUCCESS) 启动失败问题?
[root@localhost c]# systemctl status vsftpd.service ● vsftpd.service - Vsftpd ftp daemon Loaded: loa ...
- LeetCode之数据流中第一个唯一的数字
使用一个Map维护数字出现的次数,使用一个链表维护只出现一次的数,使用一个变量记录是否找到过终止数字. AC代码: public class Solution { /* * @param : a co ...
- 重载jquery on方法实现click事件在移动端的快速响应
额,这个标题取的还真是挺装的... 其实我想表达的是jquery click事件如何在移动端自动转换成touchstart事件. 因为移动端click事件会比touchstart事件慢几拍 移动设备某 ...
- HNU Joke with permutation (深搜dfs)
题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=13341&courseid=0 Joke with pe ...
- 深入理解Spring系列之十:DispatcherServlet请求分发源码分析
转载 https://mp.weixin.qq.com/s/-kEjAeQFBYIGb0zRpST4UQ DispatcherServlet是SpringMVC的核心分发器,它实现了请求分发,是处理请 ...
- Perl6多线程4: Promise allof / anyof
allof : 所有代码块执行完成后才退出 anyof :只要有一个代码块执行完后就马上退出 要配合 await 一起用: my $p = start {say 'a'}; ;say 'b';} ...
- linux内核数据结构之链表【转】
转自:http://www.cnblogs.com/Anker/p/3475643.html 1.前言 最近写代码需用到链表结构,正好公共库有关于链表的.第一眼看时,觉得有点新鲜,和我之前见到的链表结 ...
- device tree --- #address-cells and #size-cells property
device tree source Example1 / { #address-cells = <0x1>; // 在 root node 下使用 1 個 u32 來代表 address ...
- Python3中对Dict的内存优化
众所周知,python3.6这个版本对dict的实现是做了较大优化的,特别是在内存使用率方面,因此我觉得有必要研究一下最新的dict的源码实现. 前后断断续续看了大概一周多一点,主要在研究dict和创 ...