BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)
Description
考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最
大出现值。
Input
输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。
Output
输出一个整数,为逝查回文子串的最大出现值。
Sample Input
abacaba
【样例输入2]
www
Sample Output
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)的更多相关文章
- BZOJ3676:[APIO2014]回文串(SAM,Manacher)
Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. Input 输入只有一行 ...
- BZOJ3676 APIO2014回文串(manacher+后缀自动机)
由于本质不同的回文子串数量是O(n)的,考虑在对于每个回文子串在第一次找到它时对其暴力统计.可以发现manacher时若右端点移动则找到了一个新回文串.注意这样会漏掉串长为1的情况,特判一下. 现在问 ...
- bzoj3676 [Apio2014]回文串 卡常+SAM+树上倍增
bzoj3676 [Apio2014]回文串 SAM+树上倍增 链接 bzoj luogu 思路 根据manacher可以知道,每次暴力扩展才有可能出现新的回文串. 所以推出本质不同的回文串个数是O( ...
- [模板] 回文树/回文自动机 && BZOJ3676:[Apio2014]回文串
回文树/回文自动机 放链接: 回文树或者回文自动机,及相关例题 - F.W.Nietzsche - 博客园 状态数的线性证明 并没有看懂上面的证明,所以自己脑补了一个... 引理: 每一个回文串都是字 ...
- [BZOJ3676][APIO2014]回文串(Manacher+SAM)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 3097 Solved: 1408[Submit][Statu ...
- [Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)
3676: [Apio2014]回文串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 3396 Solved: 1568[Submit][Statu ...
- [bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增
Brief Description 一个回文串的value定义为这个回文串的长度乘以出现次数.给定一个字符串,求\(value_{max}\). Algorithm Design 我们使用Manach ...
- BZOJ3676 APIO2014 回文串 Manacher、SA
传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...
- bzoj3676: [Apio2014]回文串 pam
题意:字符串s.我们定义s的一个子串t的"出 现值"为t在s中的出现次数乘以t的长度.请你求出s的所有回文子串中的最 大出现值. 题解:pam板子题 //cnt数组表示该节点代表的 ...
随机推荐
- HDU44979 GCD and LCM (素因子分解+计数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4497 题意: 求有多少种(x,y,z)使得最小公倍数为l,最大公约数为g 分析: 我们将l,g进行素因 ...
- poj2002 哈希
Squares Time Limit: 3500MS Memory Limit: 65536K Total Submissions: 17666 Accepted: 6735 Descript ...
- POJ 1682 DP
原创: http://www.cnblogs.com/proverbs/archive/2012/10/03/2711151.html 超高仿: http://blog.csdn.net/mars_c ...
- Weka中数据挖掘与机器学习系列之基本概念(三)
数据挖掘和机器学习 数据挖掘和机器学习这两项技术的关系非常密切.机器学习方法构成数据挖掘的核心,绝大多数数据挖掘技术都来自机器学习领域,数据挖掘又向机器学习提出新的要求和任务. 数据挖掘就是在数据中寻 ...
- 编写jsp代码时出现的红色提示线错误
将jsp页面关闭:点击"X"号,例如图中的index.jsp页面的”X"号,或者右键—“close"也可以. 双击jsp页面:重新启动页面,页面的错误提示线 ...
- Codeforces Round #240 (Div. 2) 题解
A: 1分钟题,往后扫一遍 int a[MAXN]; int vis[MAXN]; int main(){ int n,m; cin>>n>>m; MEM(vis,); ; i ...
- printf---格式化并输出结果到标准输出。
printf命令格式化并输出结果到标准输出. 语法 printf(选项)(参数) --help:在线帮助: --version:显示版本信息. 参数 输出格式:指定数据输出时的格式: 输出字符串:指定 ...
- 【Uva 1601】The Morning after Halloween
[Link]: [Description] 给你一张平面图; 最多可能有3只鬼; 给出这几只鬼的初始位置; 然后,这几只鬼有各自的终点; 每秒钟,这几只鬼能同时移动到相邻的4个格子中的一个 任意两只鬼 ...
- 【Eclipse中使用Git之一】把远程仓库的项目,clone到eclipse里面
[Eclipse中使用Git之一]把远程仓库的项目,clone到eclipse里面 2015-01-29 19:25 15779人阅读 评论(1) 收藏 举报 .embody{ padding:10p ...
- Transport Tablespace Set(三) ----transport single tablespace
源端字符集与endian查看: SQL> select userenv('language') from dual; USERENV('LANGUAGE') SIMPLIFIED CHINESE ...