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。

Solution

垃圾题目卡$SAM+Manacher$做法的空间……害我把所有的结构体全拆开还把$SAM$的$son$数组换成了$map$才过……

首先众所周知,一个串的本质不同的回文子串只有$O(n)$级别,且在$Manacher$过程中右端点右移的情况就是本质不同的回文子串。所以我们可以做一遍$Manacher$把本质不同的回文子串求出来。

假设现在的一个回文子串是$S_{l,r}$,设$SAM$插入$r$的时候的$np$节点为$node_r$,那么我们知道,$S_{l,r}$一定是$node_r$代表的子串的一个后缀,且$S_{l,r}$的出现次数是$right_{node_r}$。

我们可以倍增从$node_r$往上跳,因为越往上跳$right$越大。跳到长度取值范围包括$r-l+1$的节点然后更新答案就可以了。

Code

  1. #include<iostream>
  2. #include<cstring>
  3. #include<cstdio>
  4. #include<map>
  5. #define N (600009)
  6. #define LL long long
  7. using namespace std;
  8.  
  9. int to[N],nxt[N];
  10. int n,m,pos[N],len[N];
  11. int Depth[N],f[N][];
  12. int head[N],num_edge;
  13. int p,q,np,nq,last=,cnt=;
  14. int fa[N],rig[N],step[N],node[N];
  15. map<int,int>son[N];
  16. LL ans;
  17. char s[N>>],t[N];
  18.  
  19. void add(int u,int v)
  20. {
  21. to[++num_edge]=v;
  22. nxt[num_edge]=head[u];
  23. head[u]=num_edge;
  24. }
  25.  
  26. void Insert(int x)
  27. {
  28. p=last; np=last=++cnt; step[np]=step[p]+; rig[np]=;
  29. while (!son[p][x] && p) son[p][x]=np, p=fa[p];
  30. if (!p) fa[np]=;
  31. else
  32. {
  33. q=son[p][x];
  34. if (step[q]==step[p]+) fa[np]=q;
  35. else
  36. {
  37. nq=++cnt; step[nq]=step[p]+;
  38. son[nq]=son[q];
  39. fa[nq]=fa[q]; fa[q]=fa[np]=nq;
  40. while (son[p][x]==q) son[p][x]=nq, p=fa[p];
  41. }
  42. }
  43. }
  44.  
  45. void DFS(int x,int fa)
  46. {
  47. Depth[x]=Depth[fa]+; f[x][]=fa;
  48. for (int i=; i<=; ++i) f[x][i]=f[f[x][i-]][i-];
  49. for (int i=head[x]; i; i=nxt[i])
  50. DFS(to[i],x), rig[x]+=rig[to[i]];
  51. }
  52.  
  53. void Calc()
  54. {
  55. for (int i=; i<n; ++i) Insert(s[i]-'a'), node[i]=np;
  56. for (int i=; i<=cnt; ++i) add(fa[i],i);
  57. DFS(,);
  58. }
  59.  
  60. void Solve(int p,int k)
  61. {
  62. while (t[p+k]=='#' || t[p+k]==')') --k;
  63. int x=node[pos[p+k]],y=pos[p+k]-pos[p-k]+;
  64. for (int i=; i>=; --i) if (step[f[x][i]]>=y) x=f[x][i];
  65. ans=max(ans,1ll*rig[x]*y);
  66. }
  67.  
  68. void Manacher()
  69. {
  70. t[++m]='(';
  71. for (int i=; i<n; ++i) t[++m]='#', t[++m]=s[i], pos[m]=i;
  72. t[++m]='#'; t[++m]=')';
  73.  
  74. int x,mid=,maxn=;
  75. for (int i=; i<=m; ++i)
  76. {
  77. if (i>maxn) x=;
  78. else x=min(maxn-i+,len[mid*-i]);
  79. while (t[i+x]==t[i-x]) Solve(i,x), ++x;
  80. len[i]=x;
  81. if (i+x->maxn) maxn=i+x-, mid=i;
  82. }
  83. }
  84.  
  85. int main()
  86. {
  87. scanf("%s",s); n=strlen(s);
  88. Calc(); Manacher();
  89. printf("%lld\n",ans);
  90. }

BZOJ3676:[APIO2014]回文串(SAM,Manacher)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ3676: [Apio2014]回文串(SAM+Manacher/PAM)

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

  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. 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)

    传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...

随机推荐

  1. wpf 控件大小随窗体大小改变而改变

    WPF可以直接通过设置图形类控件的水平和垂直Alighment为Stretch实现用一个ViewBox装上所有的Window内容然后当window缩放时就可以一起放大缩小了ViewBox的显示机制是, ...

  2. JavaSE Collection集合

    集合:是java中提供的一种容器,可以用来存储多个对象.可是我们前面学习的数组也是可以保存多个对象的,为什么还要提供集合容器呢?集合和数组它们有啥区别呢? 数组的长度是固定的.一旦创建完成不能改变长度 ...

  3. Re0:从零学习node.js

    起小项目 express xxx 镜像 npm install npm install npm start 创建自己的端口...

  4. 初学HTML-4

    img标签:<img src=" "> src——source缩写,告诉img标签需要显示的图片名称 属性:width:宽度   height:高度.若未指定宽和高,则 ...

  5. js-ES6学习笔记-Generator函数

    1.Generator 函数是 ES6 提供的一种异步编程解决方案.形式上,Generator 函数是一个普通函数,但是有两个特征.一是,function关键字与函数名之间有一个星号:二是,函数体内部 ...

  6. 从零开始学习html(十)CSS格式化排版——下

    六.文字排版--删除线 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type&q ...

  7. 小记SharePoint REST API Search和COM

    1.管理员身份Visual Studio,新建类项目 SPCOM 2.编写逻辑实现代码 重点关注搜索结果的属性包括: Title,Author,Path,Description,HitHighligh ...

  8. FineReport单行与数据库交互的方法

    1.   问题描述 我们在做一张报表填报的时候经常会遇到需要在一行进行添加动作,将该行数据直接与数据库交互,执行存储过程过程.我们可以通过每一行增加帆软“插入”按钮实现插入动作,并且在控件事件中增加和 ...

  9. 企业如何选择合适的BI工具?

    在没认清现状前,企业当然不能一言不合就上BI. BI不同于一般的企业管理软件,不能简单归类为类似用于提高管理的ERP和WMS,或用于提高企业效率的OA.BPM.BI的本质应该是通过展现数据,用于加强企 ...

  10. 带你从零学ReactNative开发跨平台App开发(一)

    ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...