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

解题思路:

1.Manacher+SAM

首先,是不是有人告诉过你本质不同的回文串有O(n)个,就是在Manacher中学过的。

每次在Manacher扩展f[i]时将其在SAM的Parent树中匹配,就是len*wgt最大值。

代码:

 #include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
const int N=;
const int M=;
struct sant{
int tranc[];
int len;
int pre;
}s[N];
struct pnt{
int hd;
int fa[];
int wgt;
}p[N];
int cnt;
int dfn;
int siz;
int fin;
int len,m;
lnt ans;
char tmp[M];
int str[M<<];
int f[N];
int pos[M<<];
int endpos[M];
int has[N];
int topo[N];
void Insert(int c)
{
int nwp,nwq,lsp,lsq;
nwp=++siz;
p[nwp].wgt=;
s[nwp].len=s[fin].len+;
for(lsp=fin;lsp&&!s[lsp].tranc[c];lsp=s[lsp].pre)
s[lsp].tranc[c]=nwp;
if(!lsp)
s[nwp].pre=;
else{
lsq=s[lsp].tranc[c];
if(s[lsq].len==s[lsp].len+)
s[nwp].pre=lsq;
else{
nwq=++siz;
s[nwq]=s[lsq];
s[nwq].len=s[lsp].len+;
s[nwp].pre=s[lsq].pre=nwq;
while(s[lsp].tranc[c]==lsq)
{
s[lsp].tranc[c]=nwq;
lsp=s[lsp].pre;
}
}
}
fin=nwp;
return ;
}
int check(int l,int r)
{
if(l<||r>len)
return ;
int root=endpos[r];
for(int i=;i>=;i--)
{
if(s[p[root].fa[i]].len>=r-l+)
root=p[root].fa[i];
}
ans=std::max(ans,(lnt)(r-l+)*(lnt)(p[root].wgt));
return (r-l+)*p[root].wgt;
}
int main()
{
scanf("%s",tmp+);
fin=++siz;
len=strlen(tmp+);
for(int i=;i<=len;i++)
{
Insert(tmp[i]-'a');
endpos[i]=fin;
}
for(int i=;i<=siz;i++)
has[s[i].len]++;
for(int i=;i<=siz;i++)
has[i]+=has[i-];
for(int i=;i<=siz;i++)
topo[has[s[i].len]--]=i;
for(int i=siz;i;i--)
{
int x=topo[i];
p[s[x].pre].wgt+=p[x].wgt;
}
for(int i=;i<=siz;i++)
{
int x=topo[i];
p[x].fa[]=s[x].pre;
p[].fa[]=;
for(int j=;j<=;j++)
p[x].fa[j]=p[p[x].fa[j-]].fa[j-];
}
int tmpl=;
str[++tmpl]='*';
for(int i=;i<=len;i++)
{
str[++tmpl]='#';
str[++tmpl]=tmp[i];
pos[tmpl]=i;
}
str[++tmpl]='#';
str[++tmpl]='$';
int now=;
for(int i=;i<=tmpl;i++)
{
f[i]=std::min(f[now]+now-i,f[now*-i]);
f[i]=std::max(f[i],);
check(pos[i-f[i]+],pos[i+f[i]-]);
while(str[i-f[i]]==str[i+f[i]])
{
f[i]++;
check(pos[i-f[i]+],pos[i+f[i]-]);
}
if(f[now]+now<f[i]+i)
now=i;
}
printf("%lld\n",ans);
return ;
}

2.PAM模板

 #include<cstdio>
#include<cstring>
#include<algorithm>
typedef long long lnt;
struct pant{
int tranc[];
int pre;
int len;
int wgt;
};
namespace PAM{
pant h[];
int siz;
int fin;
void Res(void)
{
fin=;
siz=;
h[].pre=h[].pre=;
h[].len=-;
return ;
}
bool mismatch(char *a,int i,int pa)
{
return a[i-h[pa].len-]!=a[i];
}
void Insert(char *a,int i)
{
int nwp,lsp,mac;
lsp=fin;
int c=a[i]-'a';
while(mismatch(a,i,lsp))
lsp=h[lsp].pre;
if(!h[lsp].tranc[c])
{
nwp=++siz;
mac=h[lsp].pre;
h[nwp].len=h[lsp].len+;
while(mismatch(a,i,mac))
mac=h[mac].pre;
h[nwp].pre=h[mac].tranc[c];
h[lsp].tranc[c]=nwp;
}
fin=h[lsp].tranc[c];
h[fin].wgt++;
return ;
}
lnt build(void)
{
lnt ans=;
for(int i=siz;i;i--)
{
h[h[i].pre].wgt+=h[i].wgt;
ans=std::max(ans,(lnt)(h[i].len)*(lnt)(h[i].wgt));
}
return ans;
}
}
char tmp[];
int main()
{
PAM::Res();
scanf("%s",tmp+);
int len=strlen(tmp+);
for(int i=;i<=len;i++)
PAM::Insert(tmp,i);
printf("%lld\n",PAM::build());
return ;
}

BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)的更多相关文章

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

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

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

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

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

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

  4. [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串

    回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...

  5. [BZOJ3676][APIO2014]回文串(Manacher+SAM)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 3097  Solved: 1408[Submit][Statu ...

  6. [Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 3396  Solved: 1568[Submit][Statu ...

  7. [bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增

    Brief Description 一个回文串的value定义为这个回文串的长度乘以出现次数.给定一个字符串,求\(value_{max}\). Algorithm Design 我们使用Manach ...

  8. BZOJ3676 APIO2014 回文串 Manacher、SA

    传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...

  9. bzoj3676: [Apio2014]回文串 pam

    题意:字符串s.我们定义s的一个子串t的"出 现值"为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. 题解:pam板子题 //cnt数组表示该节点代表的 ...

随机推荐

  1. localStorage 以及UserData[IE6 IE7]使用

    说在前头: UserData:属于IE6 IE7的老东西.麻烦且体验差,暂且不表 localStorage 属于HTML5的东西,兼容IE8以及其它W3C标准的主流浏览器.所以尽可能的具体解说 注意: ...

  2. STL 之 hash_map源代码剖析

    // Filename: stl_hash_map.h // hash_map和hash_multimap是对hashtable的简单包装, 非常easy理解 /* * Copyright (c) 1 ...

  3. Can’t connect to local MySQL server through socket ‘/tmp/mysql/mysql.sock’解决方法

    原因在于/tmp/mysql/mysql.sock不存在,为/usr/local/mysql/mysql.sock建立一个软连接到/tmp/mysql/mysql.sock即可. ln -s /usr ...

  4. Gym - 100338E Numbers 贪心

    Gym - 100338E 题意:给你n,k问在1-n中能整出k的字典序最小的数.范围1018 思路:比较简单的贪心了,枚举10的幂m,然后加上k-m%k, 更新答案就可以了,数据一定要用unsign ...

  5. HTTP 各种特性应用(一)

    一. CORS 预请求 允许方法: GET. HEAD. POST 这三个方法 不需要预请求. 允许 Content-Type text/plain. multipart/form-data. app ...

  6. [工具] UltraEdit使用技巧汇总

    ltraEdit是一套功能强大的文本编辑器,可以编辑文本.十六进制.ASCII码,可以取代记事本,内建英文单字检查.C++及VB指令突显,可同时编辑多个文件,而且即使开启很大的文件速度也不会慢.说到编 ...

  7. HRBUST 1818 石子合并问题--直线版

    石子合并问题--直线版 Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HRBUST. Original ...

  8. 使用表单向action提交时出现 “Error setting expression 'button' with value……”

    原因是,form中的组件设置了name属性,struts2会通过OGNL在action中找相应的属性. 如 <form action="login"> <intp ...

  9. 循环GridControl所有行

    ; i < gridView1.RowCount; i++) { DataRowView row = (DataRowView)gridView1.GetRow(i); } gridView1是 ...

  10. 使用cocos2dx 3.2和cocosstudio屏幕适配总结----相对布局

    屏幕适配的文章太多了,基本上都是理论性的东西.大家明确了机制就知道了.没有完美的适配方案,除非你们的美工愿意折腾. 常规策略: 今天研究了一下屏幕适配导致的缩放和展示不全的问题(黑边的方案直接淘汰). ...