考虑枚举回文中心,然后向两边扩展,当匹配到当前串的边界的时候,枚举下一个串接上。

这个过程可以通过记忆化搜索来完成,设:

$f[i][0]$表示对于$i$这个位置,$[i,串结尾]$等待匹配的最长回文子串。

$f[i][1]$表示对于$i$这个位置,$[串开头,i]$等待匹配的最长回文子串。

如果在转移的过程中发现两个串都已经匹配到了边界,或者转移有环,那么说明答案无限。

用后缀数组支持lcp的询问,时间复杂度$O(nL+L\log L)$。

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. const int N=400010,M=105;
  7. int n,m,i,j,k,x,y,st[M],en[M],from[N],f[N][2],v[N][2],vis[N][2],ans;char a[N],s[N];
  8. namespace SA{
  9. int n,rk[N],sa[N],height[N],tmp[N],cnt[N],Log[N],f[18][N];char s[N];
  10. void build(int n,int m){
  11. int i,j,k;n++;
  12. for(i=0;i<n;i++)cnt[rk[i]=s[i]]++;
  13. for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
  14. for(i=0;i<n;i++)sa[--cnt[rk[i]]]=i;
  15. for(k=1;k<=n;k<<=1){
  16. for(i=0;i<n;i++){
  17. j=sa[i]-k;
  18. if(j<0)j+=n;
  19. tmp[cnt[rk[j]]++]=j;
  20. }
  21. sa[tmp[cnt[0]=0]]=j=0;
  22. for(i=1;i<n;i++){
  23. if(rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k])cnt[++j]=i;
  24. sa[tmp[i]]=j;
  25. }
  26. memcpy(rk,sa,n*sizeof(int));
  27. memcpy(sa,tmp,n*sizeof(int));
  28. if(j>=n-1)break;
  29. }
  30. for(j=rk[height[i=k=0]=0];i<n-1;i++,k++)
  31. while(~k&&s[i]!=s[sa[j-1]+k])height[j]=k--,j=rk[sa[j]+1];
  32. for(i=2;i<n;i++)Log[i]=Log[i>>1]+1;
  33. for(i=1;i<n;i++)f[0][i]=height[i];
  34. for(j=1;j<18;j++)for(i=1;i+(1<<j)-1<n;i++)f[j][i]=min(f[j-1][i],f[j-1][i+(1<<(j-1))]);
  35. }
  36. inline int ask(int x,int y){
  37. int k=Log[y-x+1];
  38. return min(f[k][x],f[k][y-(1<<k)+1]);
  39. }
  40. inline int lcp(int x,int y){
  41. if(x==y)return N;
  42. x=rk[x],y=rk[y];
  43. if(x>y)swap(x,y);
  44. return ask(x+1,y);
  45. }
  46. }
  47. inline int query(int x,int y){
  48. return min(SA::lcp(x,m-1-y),min(en[from[x]]-x,y-st[from[y]])+1);
  49. }
  50. void getinf(){
  51. puts("Infinity");
  52. exit(0);
  53. }
  54. int dfs(int u,int p){
  55. if(vis[u][p])getinf();
  56. if(v[u][p])return f[u][p];
  57. v[u][p]=vis[u][p]=1;
  58. int&ret=f[u][p];
  59. if(!p){
  60. for(int i=1;i<=n;i++){
  61. int k=query(u,en[i]);
  62. int x=u+k-1,y=en[i]-k+1;
  63. if(x<en[from[u]]&&y>st[i])ret=max(ret,k*2);
  64. else if(x==en[from[u]]&&y==st[i])getinf();
  65. else if(x==en[from[u]])ret=max(ret,k*2+dfs(y-1,1));
  66. else ret=max(ret,k*2+dfs(x+1,0));
  67. }
  68. }else{
  69. for(int i=1;i<=n;i++){
  70. int k=query(st[i],u);
  71. int x=u-k+1,y=st[i]+k-1;
  72. if(x>st[from[u]]&&y<en[i])ret=max(ret,k*2);
  73. else if(x==st[from[u]]&&y==en[i])getinf();
  74. else if(x==st[from[u]])ret=max(ret,k*2+dfs(y+1,0));
  75. else ret=max(ret,k*2+dfs(x-1,1));
  76. }
  77. }
  78. vis[u][p]=0;
  79. return ret;
  80. }
  81. int main(){
  82. scanf("%d",&n);
  83. for(i=1;i<=n;i++){
  84. scanf("%s",a);
  85. st[i]=m;
  86. for(j=0;a[j];j++)from[m]=i,s[m++]=a[j];
  87. en[i]=m-1;
  88. }
  89. m<<=1;
  90. for(i=0,j=m-1;i<j;i++,j--)s[j]=s[i],from[j]=from[i];
  91. for(SA::n=m,i=0;i<m;i++)SA::s[i]=s[i];
  92. SA::build(m,128);
  93. for(i=1;i<=n;i++)ans=max(ans,max(dfs(st[i],0),dfs(en[i],1)));
  94. for(i=1;i<=n;i++){
  95. for(j=st[i];j<=en[i];j++){
  96. k=query(j,j);
  97. x=j-k+1,y=j+k-1;
  98. if(x>st[i]&&y<en[i])ans=max(ans,k*2-1);
  99. else if(x==st[i]&&y==en[i])getinf();
  100. else if(x==st[i])ans=max(ans,k*2-1+dfs(y+1,0));
  101. else ans=max(ans,k*2-1+dfs(x-1,1));
  102. }
  103. for(j=st[i];j<en[i];j++){
  104. k=query(j+1,j);
  105. x=j-k+1,y=j+k;
  106. if(x>st[i]&&y<en[i])ans=max(ans,k*2);
  107. else if(x==st[i]&&y==en[i])getinf();
  108. else if(x==st[i])ans=max(ans,k*2+dfs(y+1,0));
  109. else ans=max(ans,k*2+dfs(x-1,1));
  110. }
  111. }
  112. return printf("%d",ans),0;
  113. }

  

BZOJ3654 : 图样图森破的更多相关文章

  1. P3900 [湖南集训]图样图森破

    P3900 [湖南集训]图样图森破 链接 分析: 感觉像个暴力. 可以枚举回文串的回文中心,即枚举一个串,枚举一个串的位置作为回文中心,然后求出这个串内的回文串的长度. 此时如果回文串两端都没有到这个 ...

  2. Bzoj 3654 图样图森波 题解

    3654: 图样图森破 Time Limit: 30 Sec  Memory Limit: 512 MBSubmit: 123  Solved: 66[Submit][Status][Discuss] ...

  3. ES6 箭头函数中的 this?你可能想多了(翻译)

    箭头函数=>无疑是ES6中最受关注的一个新特性了,通过它可以简写 function 函数表达式,你也可以在各种提及箭头函数的地方看到这样的观点——“=> 就是一个新的 function”. ...

  4. Windbg Extension NetExt 使用指南 【2】 ---- NetExt 的基本命令介绍

    摘要 : 本章节介绍NetExt常用的命令. 并且对SOS进行一些对比. NetExt的帮助 要想玩好NetExt, 入门就得看帮助. 看NetExt的帮助可以调用!whelp 命令. 这样hi列举出 ...

  5. 自己动手之使用反射和泛型,动态读取XML创建类实例并赋值

    前言: 最近小匹夫参与的游戏项目到了需要读取数据的阶段了,那么觉得自己业余时间也该实践下数据相关的内容.那么从哪入手呢?因为用的是Unity3d的游戏引擎,思来想去就选择了C#读取XML文件这个小功能 ...

  6. Hadoop学习之旅三:MapReduce

    MapReduce编程模型 在Google的一篇重要的论文MapReduce: Simplified Data Processing on Large Clusters中提到,Google公司有大量的 ...

  7. [LeetCode] Maximum Size Subarray Sum Equals k 最大子数组之和为k

    Given an array nums and a target value k, find the maximum length of a subarray that sums to k. If t ...

  8. [LeetCode] Pow(x, n) 求x的n次方

    Implement pow(x, n). 这道题让我们求x的n次方,如果我们只是简单的用个for循环让x乘以自己n次的话,未免也把LeetCode上的想的太简单了,一句话形容图样图森破啊.OJ因超时无 ...

  9. [LeetCode] Median of Two Sorted Arrays 两个有序数组的中位数

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

随机推荐

  1. ArrayList 和 LinkedList 的区别

    1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构.2.对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动 ...

  2. MVC – 4.mvc初体验(2)

    5.显示学员列表 效果 数据表 5.1 首先,在文件夹Models新建一个新建项(W),选择ADO.NET 实体数据模型 (SingleTest.edmx) 5.2 建一个控制器,StudentsCo ...

  3. Linux 标准目录结构

    初学Linux,首先需要弄清Linux 标准目录结构 / root --- 启动Linux时使用的一些核心文件.如操作系统内核.引导程序Grub等. home --- 存储普通用户的个人文件 ftp ...

  4. Delphi中线程类TThread实现多线程编程1---构造、析构……

    参考:http://www.cnblogs.com/rogee/archive/2010/09/20/1832053.html Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大 ...

  5. Shell编程基础教程7--脚本参数的传递

    7.脚本参数的传递    7.1.shift命令        简介:            shift n        每次将参数位置向左偏移n位        例子 #!/bin/bash us ...

  6. 攻城狮在路上(壹) Hibernate(十五)--- Hibernate的高级配置

    一.配置数据库连接池: 1.使用默认的数据库连接池: Hibernate提供了默认了数据库连接池,它的实现类为DriverManegerConnectionProvider,如果在Hibernate的 ...

  7. PHP获取用户真实IP

    function get_client_ip() { if(getenv('HTTP_CLIENT_IP') && strcasecmp(getenv('HTTP_CLIENT_IP' ...

  8. [Linux][VMWare] 学习笔记之安装Linux系统-网络配置

    最近开始折腾Linux,在本机装了个VMWare和Centos,装完之后虚拟机里面的OS可以上网,但是使用SecureCRT连接不上虚拟机,开始折腾这个网络. vmware安装好以后,会自动添加两张网 ...

  9. 接口API测试和返回值JSON解析的插件

    火狐插件1.   HttpRequest作用:接口API测试例子:http://192.168.10.61:8080/ZHCS/user/loginApp.do?phone=admin&pwd ...

  10. 求CRC校验和的低位和高位的两种方式

    方式1 unsigned ; // 校验和 ]; memcpy(tstCRCChecksum,&shrCRCCheckSum,); // shrCRCCheckSum:216D LOGI(]) ...