题目

非常板子了

看到求什么最长的回文,我们就想到枚举回文中心的方法

首先对于这个回文串只包含在一个串内的情况,我们随便一搞就可以了,大概\(Manacher\)一下就没有了

对于那种扭动的回文串,我们枚举回文中心,求一下回文半径,我们发现其必须先在一个串内扩展一个最长回文半径的长度,再去另外一个串扩展才是最优的

于是我们对这个两个串正反建\(SA\)求一下\(lcp\)就没了

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
const int maxn=4e5+10;
char A[100005],B[100005],S[maxn];
int sa[maxn],rk[maxn],tax[maxn],tp[maxn],het[maxn];
int lg[maxn],St[maxn][20];
int ans=0,L,n,m;
int a[200005][2],b[200005][2];
inline void qsort() {
for(re int i=0;i<=m;i++) tax[i]=0;
for(re int i=1;i<=L;i++) tax[rk[i]]++;
for(re int i=1;i<=m;i++) tax[i]+=tax[i-1];
for(re int i=L;i;--i) sa[tax[rk[tp[i]]]--]=tp[i];
}
inline int ask(int l,int r) {
int k=lg[r-l+1];
return min(St[l][k],St[r-(1<<k)+1][k]);
}
inline int LCP(int i,int j) {
if(rk[i]>rk[j]) std::swap(i,j);
return ask(rk[i]+1,rk[j]);
}
int main() {
scanf("%d",&n);
scanf("%s",A+1);scanf("%s",B+1);
for(re int i=1;i<=n;i++) S[i]=A[i],a[i][0]=i;
L=n+1;S[L]='$';
for(re int i=1;i<=n;i++)S[++L]=B[i],b[i][0]=L;
S[++L]='#';
for(re int i=n;i;--i) S[++L]=A[i],a[i][1]=L;
S[++L]='&';
for(re int i=n;i;--i) S[++L]=B[i],b[i][1]=L;
for(re int i=1;i<=L;i++) rk[i]=S[i],tp[i]=i;
m=255;qsort();
for(re int w=1,p=0;p<L;w<<=1,m=p) {
p=0;
for(re int i=1;i<=w;i++) tp[++p]=L-w+i;
for(re int i=1;i<=L;i++) if(sa[i]>w) tp[++p]=sa[i]-w;
qsort();
for(re int i=1;i<=L;i++) std::swap(rk[i],tp[i]);
rk[sa[1]]=p=1;
for(re int i=2;i<=L;i++)
rk[sa[i]]=(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+w]==tp[sa[i-1]+w])?p:++p;
}
int k=0;
for(re int i=1;i<=L;i++) {
if(k) --k;
int j=sa[rk[i]-1];
while(S[i+k]==S[j+k]) ++k;
het[rk[i]]=k;
}
for(re int i=2;i<=L;i++) lg[i]=lg[i>>1]+1;
for(re int i=1;i<=L;i++) St[i][0]=het[i];
for(re int j=1;j<=lg[L];j++)
for(re int i=1;i+(1<<j)-1<=L;i++)
St[i][j]=min(St[i][j-1],St[i+(1<<(j-1))][j-1]);
for(re int i=1;i<n;i++) {
int now=LCP(a[i+1][0],a[i][1]);
ans=max(2*now,ans);
if(i-now>=1) {
int t=LCP(a[i-now][1],b[i+now][0]);
ans=max(ans,2*(now+t));
}
}
for(re int i=1;i<n;i++) {
int now=LCP(b[i+1][0],b[i][1]);
ans=max(2*now,ans);
if(i+now+1<=n) {
int t=LCP(b[i+1+now][0],a[i-now+1][1]);
ans=max(ans,2*(now+t));
}
}
for(re int i=2;i<n;i++) {
int now=LCP(a[i+1][0],a[i-1][1]);
ans=max(2*now+1,ans);
if(i-now-1>=1) {
int t=LCP(a[i-now-1][1],b[i+now][0]);
ans=max(ans,2*(now+t)+1);
}
}
for(re int i=2;i<n;i++) {
int now=LCP(b[i+1][0],b[i-1][1]);
ans=max(2*now+1,ans);
if(i+now+1<=n) {
int t=LCP(b[i+now+1][0],a[i-now][1]);
ans=max(ans,2*(now+t)+1);
}
}
printf("%d\n",ans);
return 0;
}

[JSOI2016]扭动的回文串的更多相关文章

  1. 【BZOJ4755】 [Jsoi2016]扭动的回文串

    BZOJ4755 [Jsoi2016]扭动的回文串 Solution 考虑对于他给出的 A中的一个回文串: B中的一个回文串: 或者某一个回文的扭动字符串S(i,j,k) 这样子几个限制,我们1,2就 ...

  2. [BZOJ]4755: [Jsoi2016]扭动的回文串

    Time Limit: 10 Sec  Memory Limit: 512 MB Description JYY有两个长度均为N的字符串A和B. 一个"扭动字符串S(i,j,k)由A中的第i ...

  3. [bzoj4755][Jsoi2016]扭动的回文串

    来自FallDream的博客,未经允许,请勿转载,谢谢. JYY有两个长度均为N的字符串A和B. 一个“扭动字符串S(i,j,k)由A中的第i个字符到第j个字符组成的子串与B中的第j个字符到第k个字符 ...

  4. 【题解】Luogu P4324 [JSOI2016]扭动的回文串

    原题传送门 这题实际挺水的 先对两个字符串分别跑马拉车 就能求出1.2类扭动回文串最大的长度 考虑第三类的扭动回文串\(S(i,j,k)\),一定可以表示为\(A(i,l)+A(l+1,j)+B(j, ...

  5. BZOJ4755: [JSOI2016]扭动的回文串——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4755 JYY有两个长度均为N的字符串A和B. 一个“扭动字符串S(i,j,k)由A中的第i个字符到 ...

  6. P4324 [JSOI2016]扭动的回文串

    传送门 对\(A\).\(B\)串各跑一遍\(manacher\),求出第\(1\).\(2\)类扭动回文串的最大长度. 考虑第三类的扭动回文串\(S(i,j,k)\),一定可以表示为\(A(i,l) ...

  7. BZOJ4755 [JSOI2016]扭动的回文串 【后缀数组】【manacher】

    题目分析: 我写了史上最丑的后缀数组,怎么办? 首先manacher一遍两个串,这样只用考虑第三问.用$作为间隔符拼接两个串,把第一个串翻转.枚举回文中心,取最长的回文串,对于剩下的部分利用LCP匹配 ...

  8. BZOJ4755 JSOI2016扭动的回文串(二分答案+哈希)

    显然答案应该是由单串以某位置为中心的极长回文串继续在另一个串里拓展得到的.枚举中间位置二分答案,哈希判断即可.注意考虑清楚怎么处理偶回文,比如像manacher一样加分隔符. #include< ...

  9. BZOJ4755:[JSOI2016]扭动的回文串

    浅谈\(Manacher\):https://www.cnblogs.com/AKMer/p/10431603.html 题目传送门:https://lydsy.com/JudgeOnline/pro ...

随机推荐

  1. 深入理解java虚拟机---4虚拟机类加载机制

    本文来源于翁舒航的博客,点击即可跳转原文观看!!!(被转载或者拷贝走的内容可能缺失图片.视频等原文的内容) 若网站将链接屏蔽,可直接拷贝原文链接到地址栏跳转观看,原文链接:https://www.cn ...

  2. RequestAnimationFrame更好的实现Javascript动画

    一直以来,JavaScript的动画都是通过定时器和间隔来实现的.虽然使用CSS transitions 和 animations使Web开发实现动画更加方便,但多年来以JavaScript为基础来实 ...

  3. c#如何判断两个对象是否相等

    在c#中判断对象相等,这是对引用类型进行判断,而不是对值类型,如果是对字符串,或者是数值进行判断相等只需要用==运算符就可以了. 对两个对象用==运算符,只能判断他们两个在内存中的地址是否一样的.   ...

  4. nginx的MainLine version、Stable version、Legacy versions

    Nginx的版本说明Mainline version:在线版本,正处于开发状态Stable version :稳定版本(一般下载使用)Legacy version :遗留版本,遗留的老的版本 Linu ...

  5. html History API

    History api 兼容性支持一下浏览器 为什么要使用History API 在AJAX给我们带来提高用户体验.减少HTTP连接数等好处的同时,也渐渐显露出一些不足之处,比如: 1.页面全是用aj ...

  6. CentOS7.4 + Hadoop2.9安装配置管理(分布式)

    1.  规划 1.1.  机器列表 NameNode SecondaryNameNode DataNodes 192.168.1.121 192.168.1.122 192.168.1.101 192 ...

  7. 生成项目目录结构(based on windows system)

    描述: 作为程序员,在工作中,我们经常会有需求,需要罗列出项目的结构图:如果手工来整理的话,太过浪费时间,其实我们可以借助tree命令来快速生成目录结构. 本文主要介绍一下,基于windows系统,如 ...

  8. 结对编程——四则运算器(UI第十组)

    博客目录: 一.问题描述                   二.设计思路                   三.UI开发过程                       四.对接过程       ...

  9. Jmeter入门--可执行元件

    一.测试片段(Test Fragment) 测试片段元素是控制器上的一种特殊的线程组,它在测试树上与线程组处于一级层级.它与线程组有所不同,因为它不执行,除非它是一个模块控制器或者是被控制器所引用时才 ...

  10. MVC 实现自定义404错误页

    直接进入正题. 在HomeController中有一个NotFound的Action方法. public ActionResult NotFound() { return View(); } 对应的视 ...