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。

  这道题要求出每一个回文串,以及出现的次数。

  先用马拉车算法求出每个位置最长的回文子串,可以证明:从每个位置上取出最长的回文串去枚举一定能枚举出最优解。

  接着对于,每个位置的最长回文子串用SA与ST快速求出其出现的次数,然而这并非正解,回文自动机才是(话说APIO2014的时候还没有这玩意儿),那时这个算法应该是最优的了。

 #include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=;
char s[maxn],S[maxn<<];
int maxl[maxn<<];
int pos[maxn<<],maxL[maxn];
int rank[maxn],Wa[maxn],Wb[maxn],Wv[maxn],Ws[maxn],sa[maxn],r[maxn];
int lcp[maxn],len;
int mm[maxn],Min[maxn][];
bool cmp(int *p,int a,int b,int l){
return p[a]==p[b]&&p[a+l]==p[b+l];
} void DA(int n,int m){
int i,j,p,*x=Wa,*y=Wb,*t;
for(i=;i<m;i++)Ws[i]=;
for(i=;i<n;i++)++Ws[x[i]=r[i]];
for(i=;i<m;i++)Ws[i]+=Ws[i-];
for(i=n-;i>=;i--)sa[--Ws[x[i]]]=i; for(j=,p=;p<n;j<<=,m=p){
for(p=,i=n-j;i<n;i++)y[p++]=i;
for(i=;i<n;i++)
if(sa[i]>=j)
y[p++]=sa[i]-j; for(i=;i<m;i++)Ws[i]=;
for(i=;i<n;i++)++Ws[Wv[i]=x[y[i]]];
for(i=;i<m;i++)Ws[i]+=Ws[i-];
for(i=n-;i>=;i--)sa[--Ws[Wv[i]]]=y[i];
for(t=x,x=y,y=t,x[sa[]]=,i=,p=;i<n;i++)
x[sa[i]]=cmp(y,sa[i],sa[i-],j)?p-:p++;
}
} void Lcp(int n){
int i,j,k=;
for(i=;i<=n;i++)rank[sa[i]]=i;
for(i=;i<n;lcp[rank[i++]]=k)
for(k?--k:k,j=sa[rank[i]-];r[j+k]==r[i+k];++k);
}
int Qmin(int l,int r){
return min(Min[l][mm[r-l+]],Min[r-(<<mm[r-l+])+][mm[r-l+]]);
} int Query(int p,int l){
int ret=,lo,hi;
hi=rank[p];lo=;
while(lo<=hi){
int mid=(lo+hi)>>;
if(Qmin(mid,rank[p])>=l)hi=mid-;
else lo=mid+;
}
ret+=rank[p]-lo+; hi=len;lo=rank[p]+;
while(lo<=hi){
int mid=(lo+hi)>>;
if(Qmin(rank[p]+,mid)>=l)lo=mid+;
else hi=mid-;
}
return ret+hi-rank[p];
} int main(){
scanf("%s",s);
len=strlen(s);
int l=;
S[l++]='#';S[l++]='&';
for(int i=;i<len;i++){
pos[l]=i;
S[l++]=s[i];
pos[l]=i+;
S[l++]='&';
}
S[l]=;
int mx=,id;
for(int i=;i<l;i++){
maxl[i]=mx>i?min(maxl[id*-i],mx-i):;
while(S[i+maxl[i]]==S[i-maxl[i]])maxl[i]++;
if(i+maxl[i]>mx){
mx=i+maxl[i];
id=i;
}
} for(int i=;i<=l;i++)
maxL[pos[i-maxl[i]+]]=max(maxL[pos[i-maxl[i]+]],maxl[i]-);
//maxL[i]原s字符串中i位置最长回文子串
for(int i=;i<len;i++)r[i]=s[i];
DA(len+,);
Lcp(len); mm[]=-;
for(int i=;i<=len;i++){
mm[i]=(i&(i-))?mm[i-]:mm[i-]+;
Min[i][]=lcp[i];
} for(int k=;k<=mm[len];k++)
for(int i=;i+(<<k)-<=len;i++)
Min[i][k]=min(Min[i][k-],Min[i+(<<(k-))][k-]); long long ans=;
for(int i=;i<len;i++){
ans=max(ans,1ll*maxL[i]*Query(i,maxL[i]));
}
printf("%lld\n",ans);
return ;
}

  然后还有一种方法,前面提过,回文自动机:

 #include <iostream>
#include <cstdio>
using namespace std;
const int maxn=;
int last,cnt,ch[maxn][],fail[maxn],len[maxn],num[maxn];
long long ans=;
char s[maxn];
int find(int i,int x){
while(s[i-len[x]-]!=s[i])x=fail[x];
return x;
}
int main(){
scanf("%s",s);
fail[]=;len[]=-;cnt=;
for(int i=;s[i];i++){
int j=find(i,last);
if(ch[j][s[i]-'a'])
last=ch[j][s[i]-'a'];
else{
len[last=++cnt]=len[j]+;
fail[last]=ch[find(i,fail[j])][s[i]-'a'];
ch[j][s[i]-'a']=last;
}
num[last]++;
}
for(int i=cnt;i>=;i--)
ans=max(ans,1ll*num[i]*len[i]),num[fail[i]]+=num[i];
printf("%lld\n",ans);
return ;
}

  超级短,超级简单,但还是有些地方要注意:

  14行的初始化不能乱改,改了挺麻烦的;21,22行是有顺序的,写反了会死循环。

字符串(马拉车算法,后缀数组,稀疏表):BZOJ 3676 [Apio2014]回文串的更多相关文章

  1. BZOJ 3676: [Apio2014]回文串

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

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

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

  3. BZOJ 3676 [Apio2014]回文串 (后缀自动机+manacher/回文自动机)

    题目大意: 给你一个字符串,求其中回文子串的长度*出现次数的最大值 明明是PAM裸题我干嘛要用SAM做 回文子串有一个神奇的性质,一个字符串本质不同的回文子串个数是$O(n)$级别的 用$manach ...

  4. ●BZOJ 3676 [Apio2014]回文串

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3676 题解: 后缀数组,Manacher,二分 首先有一个结论:一个串的本质不同的回文串的个 ...

  5. BZOJ 3676 [Apio2014]回文串(回文树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3676 [题目大意] 考虑一个只包含小写拉丁字母的字符串s. 我们定义s的一个子串t的& ...

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

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

  7. BZOJ.3676.[APIO2014]回文串(回文树)

    BZOJ 洛谷 很久之前写(抄)过一个Hash+Manacher的做法,当时十分懵逼=-= 然而是道回文树模板题. 回文树教程可以看这里(真的挺妙的). 顺便再放上MilkyWay的笔记~ //351 ...

  8. BZOJ 3676: [Apio2014]回文串 后缀自动机 Manacher 倍增

    http://www.lydsy.com/JudgeOnline/problem.php?id=3676 过程很艰难了,第一次提交Manacher忘了更新p数组,超时,第二次是倍增的第0维直接在自动机 ...

  9. bzoj 3676: [Apio2014]回文串【后缀自动机+manacher】

    用manacher找出本质不同的回文子串放在SAM上跑 #include<iostream> #include<cstdio> #include<cstring> ...

随机推荐

  1. 委托、 Lambda表达式和事件——委托

    简单示例 /* * 由SharpDevelop创建. * 用户: David Huang * 日期: 2015/7/27 * 时间: 10:22 */ using System; namespace ...

  2. Axiom3D学习日记 0.Axiom基础知识

    Axiom 3D Engine An open-source, cross-platform, managed 3D rendering engine for DirectX, XNA and Ope ...

  3. 表达式:使用API创建表达式树(2)

    一.BlockExpression类:表式一个包含可在其中定义变量的表达式序列的块.是一组表达式,类似于多个委托的 += 后的效果,其返回表达式是最后一个表达式决定.以下是BlockExpressio ...

  4. 对xml操作

    已知有一个XML文件(bookshop.xml)如下: <?xml version="1.0" encoding="gb2312" ?> <b ...

  5. Deep Learning 学习随记(七)Convolution and Pooling --卷积和池化

    图像大小与参数个数: 前面几章都是针对小图像块处理的,这一章则是针对大图像进行处理的.两者在这的区别还是很明显的,小图像(如8*8,MINIST的28*28)可以采用全连接的方式(即输入层和隐含层直接 ...

  6. js对象字符串互转

    利用原生JSON对象,将对象转为字符串 var jsObj = {}; jsObj.testArray = [1,2,3,4,5]; jsObj.name = 'CSS3'; jsObj.date = ...

  7. X-Plane数据交互

    要用X-Plane进行二次开发,免不了需要进行参数的传递,下面我们来看看与X-Plane进行数据交互都有哪些方式. 与FSX和Flightgear基本一样,X-Plane支持插件,自然也支持通过插件进 ...

  8. 【POJ2352】【树状数组】Stars

    Description Astronomers often examine star maps where stars are represented by points on a plane and ...

  9. 24种设计模式--工厂方法模式【Factory Method Pattern】

    女娲补天的故事大家都听说过吧,今天不说这个,说女娲创造人的故事,可不是“造人”的工作,这个词被现代人滥用了. 这个故事是说,女娲在补了天后,下到凡间一看,哇塞,风景太优美了,天空是湛蓝的,水是清澈的, ...

  10. 《service》-“linux命令五分钟系列”之二

    本原创文章属于<Linux大棚>博客. 博客地址为http://roclinux.cn. 文章作者为roc 希望您能通过捐款的方式支持Linux大棚博客的运行和发展.请见“关于捐款” == ...