前言

用了一种很奇怪的方法来解,即二分判断回文,再进行某些奇怪的优化。因为这个方法很奇怪,所以希望如果有问题能够 hack 一下。

题解

我们发现,这题中要求的是字符串 \(SS'SS'\),其中 \(S'\) 是 \(S\) 的反向,那么这个串长度必定为 \(4\) 的倍数。那么我们对于每个位置,寻找一组最大的 \(SS'\),然后找这前面是否有一个与他相同的 \(SS'\),如果有,那么这两组字符串组成一个双倍回文。但是问题在于对于某些情况,例如 bbbbbbbbbbb,在第 \(3\) 和 \(4\) 个字符中间以及第 \(8\) 和 \(9\) 个字符中间,都能取到长度为 \(3\) 的回文 bbb,但是他们共用了第 \(6\) 个字符,从而造成最大双倍回文子串长度为 \(3\) 的假象。为了避免这种假象的发生,同时保证答案长度的最大化,我们需要将共用的部分一分为二,各执一半。

仔细思考,我们可以发现,这一共用的部分只可能是一个字符集大小为 \(1\) 的字符串(语文不好不知道怎么表达)。因为我们知道,回文子串关于对称中心对称,即在该回文子串长度范围内与对称中心距离相同的两个字符相同,两个串共用的部分位于一个串 \(A\) 的末尾和另一个串 \(B\) 的开头,当我们把串 \(B\) 的开头映射到串 \(A\) 的开头(因为 \(A\) 串和 \(B\) 串相同)后,可以发现,只有符合字符集大小为 \(1\) ,才能符合上述性质。

因此,我们预处理时把每一段字符集大小为 \(1\) 的长度等信息做好标记,然后在计算完各位置为中心的最大回文子串长度后减去重复长度即可。

代码

#include<cstdio>
#include<map>
#include<algorithm>
typedef unsigned long long ull;
const int MAXN=500001+5;
std::map<ull,int>map;
char str[MAXN];int tail[MAXN],n,l,rs[MAXN],r,len[MAXN],bll[MAXN],now,cnt,mid;ull cc,hash1[MAXN],hash2[MAXN],pow[MAXN];
ull GetHash1(int l,int r)
{
if(l<1||l>n||r<1||r>n) return ++cc;
return hash1[r]-hash1[l-1]*pow[r-l+1];
}
ull GetHash2(int l,int r)
{
if(l<1||l>n||r<1||r>n) return ++cc;
return hash2[l]-hash2[r+1]*pow[r-l+1];
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%c",&str[i]);
if(!(str[i]>='a'&&str[i]<='z')) i--;
}
for(int i=1;i<=n;i++)
{
if(str[i]!=str[i-1]) {tail[i-1]=1;now++;}
rs[i]=now;
bll[now]++;
}
for(int i=1;i<=n;i++)
hash1[i]=hash1[i-1]*31+str[i]-'a'+1;
for(int i=n;i>=1;i--)
hash2[i]=hash2[i+1]*31+str[i]-'a'+1;
pow[0]=1;
for(int i=1;i<=n;i++)
pow[i]=pow[i-1]*31;
int ans=0,answer,aans=0,last=0;
for(int i=1;i<=n;i++)
{
cnt=0;l=1;r=std::min(i-1,n-i+1);ans=0;answer=0;
while(l<=r)
{
cnt++;
if(cnt>30) break;
mid=(l+r)>>1;
if(GetHash1(i-mid,i-1)!=GetHash2(i,i+mid-1)) {r=mid-1;} else {l=mid+1;ans=std::max(ans,mid);}
}
if(tail[i+ans-1])
ans-=std::min(ans,bll[rs[i+ans-1]])/2;
len[i]=ans;
int result=map[GetHash1(i-ans,i+ans-1)];
if(GetHash1(i-ans,i+ans-1)==GetHash1(i+ans,i+ans*3-1))
{
aans=std::max(aans,ans*4);
} }
printf("%d",aans);
return 0;
}

洛谷 P4287 [SHOI2011]双倍回文题解的更多相关文章

  1. 洛谷P4287 [SHOI2011]双倍回文(回文自动机)

    传送门 听说有大佬用manacher$O(n)$过此题……太强啦…… 说一下PAM的做法吧.(看了题解之后发现)蛮简单的 我们肯定要先建出回文自动机的 然后如果是枚举每一个节点暴跳fail指针肯定得T ...

  2. Manacher || BZOJ 2342: [Shoi2011]双倍回文 || Luogu P4287 [SHOI2011]双倍回文

    题面:[SHOI2011]双倍回文 题解:具体实现时,就是在更新mr时维护前半段是回文串的最长回文串就好了 正确性的话,因为到i时如果i+RL[i]-1<=mr,那么答案肯定在i之前就维护过了: ...

  3. P4287 [SHOI2011]双倍回文(回文树)

    题目描述 记字符串 w 的倒置为 w^R^ .例如 (abcd)^R^=dcba , (abba)^R^=abba . 对字符串x,如果 x 满足 x^R^=x ,则称之为回文:例如abba是一个回文 ...

  4. P4287 [SHOI2011]双倍回文

    题意 考虑对每个节点\(x\)维护\(lastpos_x\)表示\(x\)的所有后缀回文串中第一个\(len\leqslant len_x/2\)并且能和\(x\)最后一个字符匹配的,之后枚举节点,判 ...

  5. [SHOI2011]双倍回文 manacher

    题面: 洛谷:[SHOI2011]双倍回文‘ 题解: 首先有一个性质,本质不同的回文串最多O(n)个. 所以我们可以对于每个i,求出以这个i为结尾的最长回文串,然后以此作为长串,并判断把这个长串从中间 ...

  6. BZOJ2342: [Shoi2011]双倍回文

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 923  Solved: 317[Submit][Status ...

  7. BZOJ 2342: [Shoi2011]双倍回文 马拉车算法/并查集

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1123  Solved: 408 题目连接 http://w ...

  8. 2018.06.30 BZOJ 2342: [Shoi2011]双倍回文(manacher)

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符串 ...

  9. bzoj 2342: [Shoi2011]双倍回文 -- manacher

    2342: [Shoi2011]双倍回文 Time Limit: 10 Sec  Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符 ...

随机推荐

  1. 迭代器对象numpy.nditer在数组上进行迭代——修改数组的值

    nditer对象有另一个可选参数op_flags,默认情况下,nditer将视待迭代遍历的数组为只读对象(read-only),为了在遍历数组的同时,实现对数组元素值得修改,必须指定op_flags= ...

  2. Python3.5学习之旅——day1

    本节内容: 1.Python介绍 2.Hello World程序 3.变量\字符编码 4.用户输入 5.if-else语句 6.循环语句 一.Python介绍 Python是一种动态解释性的强类型定义 ...

  3. 软件架构,WEB - MVC,MVP,MVVM

    参考 https://www.zhihu.com/question/20148405/answer/107071448 http://www.cnblogs.com/indream/p/3602348 ...

  4. 看Web视频整理标签笔记

    原来观看web视频,初学html的时候发现记忆不太深刻,所以自己整理了一些笔记,加深记忆且方便忘记时查看.html的规范(遵循)1.一个html文件开始标签和结束标签<html></ ...

  5. python 基础之字符串方法

    字符串 print('chenxi'*8) 测试 D:\python\python.exe D:/untitled/dir/for.py chenxichenxichenxichenxichenxic ...

  6. 十二 Spring的AOP开发入门,整合Junit单元测试(AspectJ的XML方式)

    创建web项目,引入jar包 引入Spring配置文件

  7. 在spring boot中使用jasypt对配置文件中的敏感字符串加密

    在spring boot的配置文件application.property(application.yml)文件中常常配置一些密码类的字符,如果用明文则很容易被盗用,可以使用jasypt在配置密码的地 ...

  8. Java基础 -4.3

    While循环结构 while循环 public static void main(String[] args) { while(布尔表达式) { 条件满足时执行; 修改循环条件; } } do wh ...

  9. 3D_solarSys

    计算机图形学_3DsolarSys 一.软件功能        1.实现3D太阳系,有太阳.土星.土星环.地球.月球.天王星.海王星.火星.其中土星.地球.天王星.海王星.火星绕着太阳转,土星环绕着土 ...

  10. 使用java实现二叉查找树的插入,修改和删除方法

    目前使用的是根据key的hashcode来进行排序,并且没有考虑hash碰撞的问题 package com.zhou.tree; import java.util.Comparator; import ...