【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的所 ...
随机推荐
- matlab实现cart(回归分类树)
作为机器学习的小白和matlab的小白自己参照 python的 <机器学习实战> 写了一下分类回归树,这里记录一下. 关于决策树的基础概念就不过多介绍了,至于是分类还是回归..我说不清楚. ...
- 2017ACM暑期多校联合训练 - Team 2 1011 HDU 6055 Regular polygon (数学规律)
题目链接 **Problem Description On a two-dimensional plane, give you n integer points. Your task is to fi ...
- react 修改state某一属性值
1.state // 筛选框相关数据 searchSelect: { term: { value: '学期', key: '', options: [] }, type_of_personnel: { ...
- bzoj 1143 二分图最大独立集
我们可以将一个点拆成两个点x,y,那么如果存在一条i->j的路径,我们就连接xi,yj,那么答案就是n-最大匹配数. 因为i->j所以对于i与j只能选一个,那么我们只需要求出来二分图的最大 ...
- React 16 源码瞎几把解读 【前戏】 为啥组件外面非得包个标签?
〇.看前准备 1.自行clone react最新代码 2.自行搭建一个能跑react的test项目 一.看表面:那些插件 如何解析JSX 有如下一段代码: // ---- hearder.jsx 组件 ...
- ProxySQL(MGR)部署故障:'sys.gr_member_routing_candidate_status' doesn't exist
ProxySQL(MGR) 故障排查: 故障现象:runtime_mysql_servers节点状态offline_hostgroup(本案例为15) 日志关键信息: [WARNING] Group ...
- js日期工具
/** * 日期工具类 */ define(function(require, exports, module) { var constants = require("constants&q ...
- 关于text-decoration无法清除继承的问题
因为text-decoration的值可以叠加,所以即使设置了none,浏览器也是看成是叠加,而不是清除的意思.
- 016 sleep,wait,yield,join区别
1.线程通常有五种状态,创建,就绪,运行.阻塞和死亡状态.2.阻塞的情况又分为三种:(1).等待阻塞:运行的线程执行wait()方法,该线程会释放占用的所有资源,JVM会把该线程放入“等待池”中.进入 ...
- 如何使用curl命令指定ip访问url
有时我们需要测试一个url,但域名并没解析,这时为了一个简单的测试而写host或去做域名解析,显然这并不高效,而有些域名甚至是正式的域名,因此我们可有使用curl命令进行测试 方法一 curl url ...