原题传送门

这题实际挺水的

先对两个字符串分别跑马拉车

就能求出1、2类扭动回文串最大的长度

考虑第三类的扭动回文串\(S(i,j,k)\),一定可以表示为\(A(i,l)+A(l+1,j)+B(j,k)\)或\(A(i,j)+B(j,l)+B(l+1,k)\),其中,第一段与第三段对称(第一段正着Hash和第三段反着Hash相同,数据水(某八位质数都不卡),单模数hash就行),第二段是一个回文子串,三段都可以是空串。

在A、B串上枚举扭动的回文串的中心mid,不难发现,以其在原串上能扩展出的最长回文子串为第二段进行扩展一定最优。对每个mid,以最长回文子串作为第二段,在A、B串上二分第一、三段的长度,其结果一定最优

代码(极其丑,常数极大)

#include <bits/stdc++.h>
#define getchar nc
#define N 200005
#define P 19260817
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline char gc(){
char ch;
while((ch=getchar())<'A'||ch>'Z');
return ch;
}
inline int read()
{
register int x=0,f=1;register char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
inline int Min(register int a,register int b)
{
return a<b?a:b;
}
inline int Max(register int a,register int b)
{
return a>b?a:b;
}
int n,ans,p;
int a[N],b[N],sum[N],num[N],bin[N],f[N],g[N];
char ch;
inline bool check(register int l1,register int r1,register int l2,register int r2){
int x=0,y=0;
x=(sum[r1]-1ll*sum[l1-1]*bin[r1-l1+1]%P)%P;
y=(num[l2]-1ll*num[r2+1]*bin[r2-l2+1]%P)%P;
x=(x+P)%P,y=(y+P)%P;
return x==y?true:false;
}
inline int calc(register int j,register int k)
{
int l=0,r=Min(j,n-k+1),res=0;
while(l<=r)
{
int mid=l+r>>1;
if(check(j-mid+1,j,k,k+mid-1))
res=mid,l=mid+1;
else
r=mid-1;
}
return res;
}
int main()
{
n=read();
bin[0]=1;
for(register int i=1;i<=n;++i)
bin[i]=1ll*bin[i-1]*27%P;
a[0]=b[0]=0;
a[(n<<1)+2]=b[(n<<1)+2]=28;
a[1]=b[1]=27;
for(register int i=1;i<=n;++i)
ch=gc(),a[i<<1]=ch-'A'+1,a[i<<1|1]=27;
for(register int i=1;i<=n;++i)
ch=gc(),b[i<<1]=ch-'A'+1,b[i<<1|1]=27;
p=0;
for(register int i=2;i<=n<<1;++i)
{
if(i<=p+f[p])
f[i]=Min(f[(p<<1)-i],p+f[p]-i);
while(a[i-f[i]-1]==a[i+f[i]+1])
++f[i];
if(i+f[i]>p+f[p])
p=i;
}
p=0;
for(register int i=2;i<=n<<1;++i)
{
if(i<=p+g[p])
g[i]=Min(g[(p<<1)-i],p+g[p]-i);
while(b[i-g[i]-1]==b[i+g[i]+1])
++g[i];
if(i+g[i]>p+g[p])
p=i;
}
for(register int i=2;i<=n<<1;++i)
ans=Max(ans,Max(f[i],g[i]));
for(register int i=1;i<=n;++i)
sum[i]=(1ll*sum[i-1]*27%P+a[i<<1])%P;
for(register int i=n;i;--i)
num[i]=(1ll*num[i+1]*27%P+b[i<<1])%P;
int l=0,r=0;
for(register int i=2;i<=n<<1;++i)
{
l=(i-f[i]+1)>>1,r=(i+f[i])>>1;
ans=Max(ans,f[i]+(calc(l-1,r)<<1));
l=(i-g[i]+1)>>1,r=(i+g[i])>>1;
ans=Max(ans,g[i]+(calc(l,r+1)<<1));
}
write(ans);
return 0;
}

【题解】Luogu P4324 [JSOI2016]扭动的回文串的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. [JSOI2016]扭动的回文串

    题目 非常板子了 看到求什么最长的回文,我们就想到枚举回文中心的方法 首先对于这个回文串只包含在一个串内的情况,我们随便一搞就可以了,大概\(Manacher\)一下就没有了 对于那种扭动的回文串,我 ...

  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. CentOS7安装Go环境

    下载go(我的当前目录是/data/work)$wget https://studygolang.com/dl/golang/go1.10.1.linux-amd64.tar.gz$tar -xvf ...

  2. Vue.js中滚动条加载更多数据

    本文章参考:http://www.cnblogs.com/ssrsblogs/p/6108423.html 分析:1.需要判断滚动条是否到底部: 需要用到DOM的三个属性值,即scrollTop.cl ...

  3. word-break和word-wrap的使用和区别

    问题起源: 中文是一个字就是一个单词,而英文字母要有一个空格才将他们分割为一个单词:文字换行没事,主要是英文 <!DOCTYPE html> <html> <head&g ...

  4. Java8 新特性之流式数据处理

    一. 流式处理简介 在我接触到java8流式处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式处理可以在一行中实现.比如我们希望对一个包含整数的 ...

  5. sonarqube安装的坑

    1.按照官网安装 结果启动不了,看了log日志以后,发现是es报错,不能以root权限启动

  6. android json解析及简单例子+Android与服务器端数据交互+Android精彩案例【申明:来源于网络】

    android json解析及简单例子+Android与服务器端数据交互+Android精彩案例[申明:来源于网络] android json解析及简单例子:http://www.open-open. ...

  7. 【Linux内存源码分析】vmalloc不连续内存管理(转)

    https://www.jeanleo.com/2018/09/09/%E3%80%90linux%E5%86%85%E5%AD%98%E6%BA%90%E7%A0%81%E5%88%86%E6%9E ...

  8. MSCKF_VIO:MSCKF的双目版本

    论文:MSCKF的双目版本 Robust Stereo Visual Inertial Odometry for Fast Autonomous Flight 下载地址:点击 源码地址:https:/ ...

  9. python-----函数参数类型

    #函数参数类型:1 位置参数 2 默认参数 3 关键字参数 4可变参数 包裹位置参数*args 包裹关键字参数 **kargs#参数位置顺序:先位置参数,默认参数,包裹位置,包裹关键字(定义和调用都应 ...

  10. windows 10 超级优化,同时解决本地磁盘100%的问题

    windows 10 超级优化,同时解决本地磁盘100%的问题 我的系统是笔记本I7处理器,配置了web服务器IIS 和一个数据库(mysql7),同时启用了虚拟机(表中已禁用),以及安装了offic ...