3676: [Apio2014]回文串

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 2343  Solved: 1031

Description

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

Input

输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。

Output

输出一个整数,为逝查回文子串的最大出现值。

Sample Input

【样例输入l】
abacaba

【样例输入2]
www

Sample Output

【样例输出l】
7

【样例输出2]
4

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。

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+倍增)的更多相关文章

  1. BZOJ3676:[APIO2014]回文串(SAM,Manacher)

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

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

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

  3. bzoj 3676 [Apio2014]回文串(Manacher+SAM)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3676 [题意] 给定一个字符串,定义一个串的权值为长度*出现次数,求最大权的回文子串. ...

  4. 【BZOJ 3676】[Apio2014]回文串

    [链接] 链接 [题意] 给你一个字符串s. 定义一个子串的出现值为它出现的次数*字符串的长度. 让你求里面的回文子串的最大出现值 |s|<=3e5 [题解] 马拉车算法里面. 只有在回文往外扩 ...

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

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

  6. BZOJ 3676: [Apio2014]回文串

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2013  Solved: 863[Submit][Status ...

  7. bzoj 3676: [Apio2014]回文串 回文自动机

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 844  Solved: 331[Submit][Status] ...

  8. 3676: [Apio2014]回文串

    3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MB Submit: 1740 Solved: 744 [Submit][Status ...

  9. 3676: [Apio2014]回文串 求回文串长度与出现次数的最大值

    「BZOJ3676」[Apio2014] 回文串   Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所 ...

随机推荐

  1. 用django框架做自己的blog

    说明:我的系统环境是ubuntu 14.10版本的,整理这篇博客,主要是自己记性太不好了,老忘东西,教训一下自己.哈哈 参考文章 createing blog 1,part-1-creating-bl ...

  2. css3同心圆闪烁扩散效果

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  3. 2017ACM暑期多校联合训练 - Team 6 1003 HDU 6098 Inversion (模拟)

    题目链接 Problem Description Give an array A, the index starts from 1. Now we want to know Bi=maxi∤jAj , ...

  4. Django初探(模板渲染、模板语音、simple_tag、母版子版、静态配置文件)

    一.首先我们用PyCharm来创建一个Django项目 终端命令:django-admin startproject sitename 图形创建:   这样一个Django项目就创建完成了,上面可以看 ...

  5. MyBatis笔记之配置输出日志并打印输出SQL语句

    1. 引入Log4J的Maven依赖: <dependency> <groupId>log4j</groupId> <artifactId>log4j& ...

  6. JS window.name跨域封装

    JS window.name 跨域封装 function CrossDomainName(target, agent, callback, security) { if (typeof target ...

  7. D - Keiichi Tsuchiya the Drift King Gym - 102028D (几何)

    题目链接:https://cn.vjudge.net/contest/275150#problem/D 题目大意: 问你能满足那个矩形可以顺利通过的条件,然后求出最小的w 具体思路:首先,我们应该将情 ...

  8. OGG生成数据定义文件的参数NOEXTATTR

    ./defgen paramfile ./dirprm/jzjj.prm NOEXTATTR In OGG 11.2, there is a new parameter NOEXTATTR. This ...

  9. 有关mysql的innodb_flush_log_at_trx_commit参数【转】

    一.参数解释 0:log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行.该模式下在事务提交的时候,不会主动触发写入磁盘的操作. 1:每次事务 ...

  10. setitimer()

    setitimer()为Linux的API,并非C语言的Standard Library,setitimer()有两个功能,一是指定一段时间后,才执行某个function,二是每间格一段时间就执行某个 ...