前言

用了一种很奇怪的方法来解,即二分判断回文,再进行某些奇怪的优化。因为这个方法很奇怪,所以希望如果有问题能够 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. 【剑指Offer面试编程题】题目1509:树中两个结点的最低公共祖先--九度OJ

    题目描述: 给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数 ...

  2. 【JS 常用操作】全选、给后来元素增加事件

    11 //全选 $("#allCheckbox").click(function () { var checkedStatus = this.checked; //alert(ch ...

  3. LinkQueue(链队)

    今天学习了队列,因为前面写了好几个链表实现的数据结构基本上都懂了,然后大致了解了一下队列的特点,便决定用自己的理解来实现一个,然后实现了. (2018-02-14 代码更新) Head file: # ...

  4. Could not find a version that satisfies the requirement win32api (from versions: ) No matching distribution found for win32api

    pip install win32api pip install pywin32 都会提示错误,如下: Could not find a version that satisfies the requ ...

  5. 执行脚本,且以脚本名保存log

    !/bin/bash path="/sys/devices/platform/soc/fd880000.i2c-pld/i2c-0/i2c-4/i2c-15/15-0060" f_ ...

  6. 利用DOCKER实现云桌面的开发环境初步设想

    想法阶段,持续更新中 一.准备一台开发专用服务器 二.建立企业私有镜像仓库 三.建立开发环境镜像并提交到私有镜像仓库 开发镜像的要求: 1.安装vnc服务,ssh服务 vnc密码的设定 2.安装开发环 ...

  7. SpringBoot之WEB开发-专题二

    SpringBoot之WEB开发-专题二 三.Web开发 3.1.静态资源访问 在我们开发Web应用的时候,需要引用大量的js.css.图片等静态资源. 默认配置 Spring Boot默认提供静态资 ...

  8. Linux centosVMware Tomcat介绍、安装jdk、安装Tomcat

    一.Tomcat介绍 Tomcat是Apache软件基金会(Apache Software Foundation)的Jakarta项目中的一个核心项目,由Apache.Sun和其他一些公司及个人共同开 ...

  9. arduino#呼吸灯

    ; // 使用引脚号 void setup() { // nothing happens in setup } void loop() { // fade in from min to max in ...

  10. Jsp和Servlet关系

    为什么会出现Jsp? 其实对于服务器来说它只认识Servlet,我们完全可以在Servlet用resp.getWriter().write("");画出网页的界面,但是仅仅一个很简 ...