点此看题面

大致题意: 求一个字符串中有多少个长度为偶数的回文串,它的一半也是回文串。

\(Manacher\)算法

这应该是\(Manacher\)算法一道比较好的入门题,强烈建议在做这题之前先去学一学\(Manacher\)算法。

大致思路

如果你会\(Manacher\)算法,其实这题的思路应该还是比较清晰的。

只要在更新最大右边界的同时,判断每一个新出现的回文串是否为双倍回文串,并更新\(ans\)即可。

代码

#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define uint unsigned int
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define abs(x) ((x)<0?-(x):(x))
#define INF 1e9
#define Inc(x,y) ((x+=(y))>=MOD&&(x-=MOD))
#define ten(x) (((x)<<3)+((x)<<1))
#define N 500000
using namespace std;
int n;string st;
class FIO
{
private:
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (FoutSize<Fsize?Fout[FoutSize++]=ch:(fwrite(Fout,1,FoutSize,stdout),Fout[(FoutSize=0)++]=ch))
int f,FoutSize,OutputTop;char ch,Fin[Fsize],*FinNow,*FinEnd,Fout[Fsize],OutputStack[Fsize];
public:
FIO() {FinNow=FinEnd=Fin;}
inline void read(int &x) {x=0,f=1;while(!isdigit(ch=tc())) f=ch^'-'?1:-1;while(x=ten(x)+(ch&15),isdigit(ch=tc()));x*=f;}
inline void read_char(char &x) {while(isspace(x=tc()));}
inline void read_string(string &x) {x="";while(isspace(ch=tc()));while(x+=ch,!isspace(ch=tc())) if(!~ch) return;}
inline void write(int x) {if(!x) return (void)pc('0');if(x<0) pc('-'),x=-x;while(x) OutputStack[++OutputTop]=x%10+48,x/=10;while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;}
inline void write_char(char x) {pc(x);}
inline void write_string(string x) {register int i,len=x.length();for(i=0;i<len;++i) pc(x[i]);}
inline void end() {fwrite(Fout,1,FoutSize,stdout);}
}F;
class Class_Manacher//Manacher算法
{
private:
int len,p[(N<<1)+5];
char ns[(N<<1)+5];
inline void Init(string st)
{
register int i,l=st.length();
for(ns[i=0]='!',ns[len=1]='%';i<l;++i) ns[++len]=st[i],ns[++len]='%';
ns[++len]='?';
}
public:
inline int GetAns(string st)//基本上是模板,只是在更新最大右边界的同时多了一个更新ans的过程
{
register int i,j,ans=0,id,Max=0;
for(Init(st),i=1;i<len;++i)
{
p[i]=i<=Max?min(p[(id<<1)-i],p[id]+id-i):1;
while(!(ns[i-p[i]]^ns[i+p[i]])) ++p[i];
if(i+p[i]>Max)
{
if(i&1) for(j=i+(Max>i+4?((Max-i+3>>2)<<2):4);j<i+p[i];j+=4) if(p[i-(j-i>>1)]>(j-i>>1)) ans=max(ans,j-i);//首先判断长度是否为偶数,然后判断每一个新出现的回文串是否为双倍回文串,并更新ans
Max=i+p[id=i];
}
}
return ans;
}
}Manacher;
int main()
{
F.read(n),F.read_string(st),F.write(Manacher.GetAns(st));
return F.end(),0;
}

【洛谷4287】[SHOI2011] 双倍回文(Manacher算法经典题)的更多相关文章

  1. 洛谷 P4287 [SHOI2011]双倍回文题解

    前言 用了一种很奇怪的方法来解,即二分判断回文,再进行某些奇怪的优化.因为这个方法很奇怪,所以希望如果有问题能够 hack 一下. 题解 我们发现,这题中要求的是字符串 \(SS'SS'\),其中 \ ...

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

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

  3. [SHOI2011]双倍回文 manacher

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

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

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

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

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

  6. BZOJ2342:[SHOI2011]双倍回文(Manacher)

    Description   Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输出文件只有一行,即:输入数据中字符串的最长 ...

  7. [BZOJ2341][Shoi2011]双倍回文 manacher+std::set

    题目链接 发现双倍回文串一定是中心是#的回文串. 所以考虑枚举#点.发现以\(i\)为中心的双倍回文的左半部分是个回文串,其中心一定位于\(i-\frac{pal[i]-1}2\)到\(i-1\)之间 ...

  8. BZOJ 2342: [Shoi2011]双倍回文 [Manacher + set]

    题意: 求最长子串使得它有四个相同的回文串SSSS相连组成 枚举中间x 找右边的中间y满足 y-r[y]<=x y<=x+r[x]/2 用个set维护 注意中间只能是# #include ...

  9. BZOJ2342 Shoi2011 双倍回文 【Manacher】

    BZOJ2342 Shoi2011 双倍回文 Description Input 输入分为两行,第一行为一个整数,表示字符串的长度,第二行有个连续的小写的英文字符,表示字符串的内容. Output 输 ...

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

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

随机推荐

  1. centos lamp 配置

    # 1. 查看是否有httpd进程正在运行(下图是有的情况) ps -ef|grep httpd

  2. 表单和css

    表单和CSS 一.==表单== 1. form表单本身 <form name="myform" action="#" method="get&q ...

  3. Ubuntu 防火墙IP转发做NAT,内网集群共享网络(简单)

    服务器架构: 系统: Ubuntu 16.04 x64 使用自带防火墙 UFW 操作: 在有公网的服务器上,进行防火墙基本操作开启自己所需业务的端口,并按下方设置启动NAT: 其他内网机器修改网关或者 ...

  4. iOS端实现节日换肤

    本文是我在网上看到一篇不错的文章,因为之前没接触过,所以特意转过来,和大家一起分享下..以下正文: 一.问题的提出 不知道大家有没有发现, 元旦期间, 很多APP界面里的图标都换成了具有节日气氛的样式 ...

  5. PAT天梯赛L3-004 肿瘤诊断

    题目链接:点击打开链接 在诊断肿瘤疾病时,计算肿瘤体积是很重要的一环.给定病灶扫描切片中标注出的疑似肿瘤区域,请你计算肿瘤的体积. 输入格式: 输入第一行给出4个正整数:M.N.L.T,其中M和N是每 ...

  6. AT2166 Rotate 3x3

    传送门 这个题网上有两种做法,一种是树状数组的,还有一种是暴力模拟的,暴力模拟显然不够优美,所以我用的树状数组 显然可以从初状态推到目标状态,我们也可以考虑倒推回去 首先可以容易发现每列的数字是不变的 ...

  7. BZOJ 2462 [BeiJing2011]矩阵模板 矩阵哈希

    昨天卡了一天常数...然后发现吧$unsigned\space long\space long$改成$unsigned$就可以过了$qwq$ 先把每一行的前缀哈希求出,然后再竖着把每个前缀哈希值哈希起 ...

  8. ubuntu tomcat https

    1.generate key use java key tool -storepass *** 2.sign certificate sudo keytool -export -alias ### - ...

  9. Java多线程与并发——死锁与中断线程

    过多的同步有可能出现死锁,死锁的操作一般是在程序运行的时候才有可能出现. 多线程中要进行资源的共享,就需要同步,但同步过多,就可能造成死锁. 死锁例子: package com.vince; /** ...

  10. qemu 出现Could not access KVM kernel module: No such file or directory failed to initialize KVM: No such file or directory

    使用qemu命令 qemu-system-x86_64 -hda image/ubuntu-test.img -cdrom ubuntu-16.04.2-server-amd64.iso -m 102 ...