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. Runtime类中的freeMemory,totalMemory,maxMemory等几个方法

    最近在网上看到一些人讨论到Java.lang.Runtime类中的freeMemory(),totalMemory(),maxMemory ()这几个方法的一些题目,很多人感到很迷惑,为什么,在jav ...

  2. .vscode folder

    https://stackoverflow.com/questions/32964920/should-i-commit-the-vscode-folder-to-source-control Che ...

  3. JavaScript Debug调试技巧

    收藏于:https://blog.fundebug.com/2017/12/04/javascript-debugging-for-beginners/

  4. Sql Server通用分页存储过程

    Sql Server2005通用分页存储过程 CREATE PROCEDURE [dbo].[Common_GetPagedList] ( @TableName nvarchar(100), --表名 ...

  5. python 多线程学习小记

    python对于thread的管理中有两个函数:join和setDaemon setDaemon:如果在程序中将子线程设置为守护线程,则该子线程会在主线程结束时自动退出,设置方式为thread.set ...

  6. Vue常见面试题汇总

    Vue框架常见面试题   1.active-class是哪个组件的属性?嵌套路由怎么定义? 答:vue-router模块的router-link组件. 2.怎么定义vue-router的动态路由?怎么 ...

  7. 【Uva 1630】Folding

    [Link]: [Description] 你能对字符串进行压缩的操作; 即把连续出现的相同的子串改成它出现的次数+这个最基本的字符串的形式; 问你这个字符串最短能被压缩得多短; [Solution] ...

  8. 洛谷 P1705 爱与愁过火

    P1705 爱与愁过火 题目背景 (本道题目隐藏了两首歌名,找找看哪~~~) <爱与愁的故事第一弹·heartache>第三章. 爱与愁大神说这是ta的伤心指数,只不过现在好很多了,翻译只 ...

  9. Ajax核心对象——高速上手XmlHttpRequest

    引言: 非TGB的.直接跳过吧-- 从开学结束JQuery之后,计算机的进度停了一段时间.某天无聊的时候,又又一次把BS的东西拿过来看了看. 发现里面有非常多既熟悉又陌生的东西. 在学习王兴魁老师的A ...

  10. Python 面向对象 —— 多重继承

    多重继承(一个子类同时继承多个父类),容易造成混乱,即如果两个父类又相同的方法名和变量名时,无法确定继承哪一个. 正因如此,Java 等语言中并不支持多重继承(Java 是单继承多接口).Python ...