BZOJ3654 : 图样图森破
考虑枚举回文中心,然后向两边扩展,当匹配到当前串的边界的时候,枚举下一个串接上。
这个过程可以通过记忆化搜索来完成,设:
$f[i][0]$表示对于$i$这个位置,$[i,串结尾]$等待匹配的最长回文子串。
$f[i][1]$表示对于$i$这个位置,$[串开头,i]$等待匹配的最长回文子串。
如果在转移的过程中发现两个串都已经匹配到了边界,或者转移有环,那么说明答案无限。
用后缀数组支持lcp的询问,时间复杂度$O(nL+L\log L)$。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=400010,M=105;
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];
namespace SA{
int n,rk[N],sa[N],height[N],tmp[N],cnt[N],Log[N],f[18][N];char s[N];
void build(int n,int m){
int i,j,k;n++;
for(i=0;i<n;i++)cnt[rk[i]=s[i]]++;
for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
for(i=0;i<n;i++)sa[--cnt[rk[i]]]=i;
for(k=1;k<=n;k<<=1){
for(i=0;i<n;i++){
j=sa[i]-k;
if(j<0)j+=n;
tmp[cnt[rk[j]]++]=j;
}
sa[tmp[cnt[0]=0]]=j=0;
for(i=1;i<n;i++){
if(rk[tmp[i]]!=rk[tmp[i-1]]||rk[tmp[i]+k]!=rk[tmp[i-1]+k])cnt[++j]=i;
sa[tmp[i]]=j;
}
memcpy(rk,sa,n*sizeof(int));
memcpy(sa,tmp,n*sizeof(int));
if(j>=n-1)break;
}
for(j=rk[height[i=k=0]=0];i<n-1;i++,k++)
while(~k&&s[i]!=s[sa[j-1]+k])height[j]=k--,j=rk[sa[j]+1];
for(i=2;i<n;i++)Log[i]=Log[i>>1]+1;
for(i=1;i<n;i++)f[0][i]=height[i];
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))]);
}
inline int ask(int x,int y){
int k=Log[y-x+1];
return min(f[k][x],f[k][y-(1<<k)+1]);
}
inline int lcp(int x,int y){
if(x==y)return N;
x=rk[x],y=rk[y];
if(x>y)swap(x,y);
return ask(x+1,y);
}
}
inline int query(int x,int y){
return min(SA::lcp(x,m-1-y),min(en[from[x]]-x,y-st[from[y]])+1);
}
void getinf(){
puts("Infinity");
exit(0);
}
int dfs(int u,int p){
if(vis[u][p])getinf();
if(v[u][p])return f[u][p];
v[u][p]=vis[u][p]=1;
int&ret=f[u][p];
if(!p){
for(int i=1;i<=n;i++){
int k=query(u,en[i]);
int x=u+k-1,y=en[i]-k+1;
if(x<en[from[u]]&&y>st[i])ret=max(ret,k*2);
else if(x==en[from[u]]&&y==st[i])getinf();
else if(x==en[from[u]])ret=max(ret,k*2+dfs(y-1,1));
else ret=max(ret,k*2+dfs(x+1,0));
}
}else{
for(int i=1;i<=n;i++){
int k=query(st[i],u);
int x=u-k+1,y=st[i]+k-1;
if(x>st[from[u]]&&y<en[i])ret=max(ret,k*2);
else if(x==st[from[u]]&&y==en[i])getinf();
else if(x==st[from[u]])ret=max(ret,k*2+dfs(y+1,0));
else ret=max(ret,k*2+dfs(x-1,1));
}
}
vis[u][p]=0;
return ret;
}
int main(){
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%s",a);
st[i]=m;
for(j=0;a[j];j++)from[m]=i,s[m++]=a[j];
en[i]=m-1;
}
m<<=1;
for(i=0,j=m-1;i<j;i++,j--)s[j]=s[i],from[j]=from[i];
for(SA::n=m,i=0;i<m;i++)SA::s[i]=s[i];
SA::build(m,128);
for(i=1;i<=n;i++)ans=max(ans,max(dfs(st[i],0),dfs(en[i],1)));
for(i=1;i<=n;i++){
for(j=st[i];j<=en[i];j++){
k=query(j,j);
x=j-k+1,y=j+k-1;
if(x>st[i]&&y<en[i])ans=max(ans,k*2-1);
else if(x==st[i]&&y==en[i])getinf();
else if(x==st[i])ans=max(ans,k*2-1+dfs(y+1,0));
else ans=max(ans,k*2-1+dfs(x-1,1));
}
for(j=st[i];j<en[i];j++){
k=query(j+1,j);
x=j-k+1,y=j+k;
if(x>st[i]&&y<en[i])ans=max(ans,k*2);
else if(x==st[i]&&y==en[i])getinf();
else if(x==st[i])ans=max(ans,k*2+dfs(y+1,0));
else ans=max(ans,k*2+dfs(x-1,1));
}
}
return printf("%d",ans),0;
}
BZOJ3654 : 图样图森破的更多相关文章
- P3900 [湖南集训]图样图森破
P3900 [湖南集训]图样图森破 链接 分析: 感觉像个暴力. 可以枚举回文串的回文中心,即枚举一个串,枚举一个串的位置作为回文中心,然后求出这个串内的回文串的长度. 此时如果回文串两端都没有到这个 ...
- Bzoj 3654 图样图森波 题解
3654: 图样图森破 Time Limit: 30 Sec Memory Limit: 512 MBSubmit: 123 Solved: 66[Submit][Status][Discuss] ...
- ES6 箭头函数中的 this?你可能想多了(翻译)
箭头函数=>无疑是ES6中最受关注的一个新特性了,通过它可以简写 function 函数表达式,你也可以在各种提及箭头函数的地方看到这样的观点——“=> 就是一个新的 function”. ...
- Windbg Extension NetExt 使用指南 【2】 ---- NetExt 的基本命令介绍
摘要 : 本章节介绍NetExt常用的命令. 并且对SOS进行一些对比. NetExt的帮助 要想玩好NetExt, 入门就得看帮助. 看NetExt的帮助可以调用!whelp 命令. 这样hi列举出 ...
- 自己动手之使用反射和泛型,动态读取XML创建类实例并赋值
前言: 最近小匹夫参与的游戏项目到了需要读取数据的阶段了,那么觉得自己业余时间也该实践下数据相关的内容.那么从哪入手呢?因为用的是Unity3d的游戏引擎,思来想去就选择了C#读取XML文件这个小功能 ...
- Hadoop学习之旅三:MapReduce
MapReduce编程模型 在Google的一篇重要的论文MapReduce: Simplified Data Processing on Large Clusters中提到,Google公司有大量的 ...
- [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 ...
- [LeetCode] Pow(x, n) 求x的n次方
Implement pow(x, n). 这道题让我们求x的n次方,如果我们只是简单的用个for循环让x乘以自己n次的话,未免也把LeetCode上的想的太简单了,一句话形容图样图森破啊.OJ因超时无 ...
- [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 ...
随机推荐
- hadoop2.x NameNode 的共享存储实现
过去几年中 Hadoop 社区涌现过很多的 NameNode 共享存储方案, 比如 shared NAS+NFS.BookKeeper.BackupNode 和 QJM(Quorum Journal ...
- ViewPager部分源码分析一:加载数据
onMeasure()调用populate(),完成首次数据初始化. populate()维护ViewPager的page,包括mItems和mAdapter. populate(): if (cur ...
- DOM – (w3school)1.DOM 方法 + 2.DOM属性 + 3.DOM 元素
1.DOM 方法 一些 DOM 对象方法 这里提供一些您将在本教程中学到的常用方法: 方法 描述 getElementById() 返回带有指定 ID 的元素. getElementsByTa ...
- 在python3.5下安装scrapy包
此前scrapy只支持python2.x 但是最新的1.1.0rc1已结开始支持py3了 如果电脑上安装了scrapy的依赖包,诸如lxml.OpenSSL 1.你直接下载Scrapy-1.1.0rc ...
- Linux性能分析工具的安装和使用
转自:http://blog.chinaunix.net/uid-26488891-id-3118279.html Normal 0 7.8 磅 0 2 false false false EN-US ...
- 命令行登陆Oracle(包括远程登陆)
本方法适用于在cmd命令行窗口以及pl/sql登陆Oracle下登录本机或者远程Oracle. 1.首先保证在当前主机上设置了ORACLE_HOME环境变量: 例如:ORACLE_HOME=D ...
- 《Spring 3.x 企业应用开发实战》目录
图书信息:陈雄华 林开雄 编著 ISBN 978-7-121-15213-9 概述: 第1章:对Spring框架进行宏观性的概述,力图使读者建立起对Spring整体性的认识. 第2章:通过一个简单的例 ...
- 攻城狮在路上(壹) Hibernate(九)--- Hibernate的映射类型
Hibernate采用映射类型作为Java类型和SQL类型的桥梁,对应type属性.分为两种:内置映射类型和客户化映射类型.一.内置映射类型: 1.Java基本类型的Hibernate映射类型: Ja ...
- PMP 第三章 单个项目的项目管理标准
1 项目管理五大过程组分别是什么? 启动过程组 规划过程组 执行过程组 监控过程组 收尾过程组 2 启动项目组是干什么?包含哪些过程?每个阶段都需要启动吗? 启动过程组:获得授权,定义一个新项目或现有 ...
- barabasilab-networkScience学习笔记4-无标度特征
第一次接触复杂性科学是在一本叫think complexity的书上,Allen博士很好的讲述了数据结构与复杂性科学,barabasi是一个知名的复杂性网络科学家,barabasilab则是他所主导的 ...