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. +load,+initialize原理

    +load,+initialize原理 1.load 父类的load方法在子类load方法之前调用,分类的load方法在原来类load方法之后调用,依赖类的load方法会在自己之前调用,总之所有的类的 ...

  2. J2EE 读取文件路径

    在J2ee中实现java类读取webcontent/web-inf/config.xml的实现代码 ,其中../config.xml相对于classes的路径 java.net.URL url = t ...

  3. (转)javaScript call 函数的用法说明

    call 方法 请参阅 应用于:Function 对象 要求 版本 5.5 调用一个对象的一个方法,以另一个对象替换当前对象. call([thisObj[,arg1[, arg2[, [,.argN ...

  4. IIS7.5 asp+access数据库连接失败处理 64位系统

    IIS7.5 asp+access数据库连接失败处理(SRV 2008R2 x64/win7 x64) IIS7.5不支持oledb4.0驱动?把IIS运行模式设置成32位就可以了,微软没有支持出64 ...

  5. CentOS 7设置iptables防火墙开放proftpd端口

    由于ftp的被动模式是这样的,客户端跟服务器端的21号端口交互信令,服务器端开启21号端口能够使客户端登录以及查看目录.但是ftp被动模式用于传输数据的端口却不是21,而是大于1024的随机或配置文件 ...

  6. 寒哥教你学 iOS - 经验漫谈(转)

    转自http://www.cocoachina.com/ios/20150907/13339.html 本篇文章主要讲解 4个问题 load妙用 aop面向切面编程 NSNumber Or Int @ ...

  7. 谷歌地图实现车辆轨迹移动播放(google map api)

    开发技术:jquery,js baidu map api,json,ajax QQ1310651206 谷歌地图(google map api)实现车辆轨迹移动播放(google map api)

  8. c#的异或运算符

    int a = 5; int b = 30; Console.WriteLine(a^b); Console.ReadKey();  输出结果是27 这是因为 5的二进制是0000 010130的二进 ...

  9. extjs下拉框添加复选框

    给ComboBox组件配置listConfig 下拉框代码: var gyslxcm = Ext.create('Ext.form.field.ComboBox',{ id : 'gyslxcm', ...

  10. fix iis Running slow

    为什么写这个文章.因为我现在再找一个站点的访问原因..方法还是老方法.. 1. 站点是否真的挂了 a. 基本上全挂.所有请求非常缓慢或超时. b.大多数请求慢,但最终还是执行了.有可能 队列再排队 怎 ...