用Manacher算法枚举回文子串,每次在后缀数组排序后的后缀数组中二分,因为用某一后缀和其他子串分别求匹配的长度,匹配长度在排序后该后缀的两侧具有单调性(匹配长度为min{H[x]|i<=x<=j},所以对于查询min(H[x])用ST表O(n)预处理,O(1)查询即可。Manacher时间复杂度O(n),后缀数组复杂度O(nlogn),总复杂度O(nlogn)。注意二分时的边界条件!

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm> using namespace std; long long Ans;
int A[],B[],U[];
int SA[],*Rank,H[],Tmp[];
int lg2[],ST[][],p[];
char str[]; void Get_H(const int n)
{
int i,j,k=;
for(i=;i<n;H[Rank[i++]]=k)
for(k?k--:k,j=SA[Rank[i]-];str[i+k]==str[j+k];++k);
for(i=;i<=n;++i)lg2[i]=lg2[i>>]+;
for(i=;i<=n;++i)ST[i][]=H[i];
for(j=;(<<j)<=n;++j)
{
for(i=;i+(<<j)-<=n;++i)
{
ST[i][j]=min(ST[i][j-],ST[i+(<<(j-))][j-]);
}
}
return ;
} int Query(const int l,const int r)
{
int temp=lg2[r-l+];
return min(ST[l][temp],ST[r-(<<temp)+][temp]);
} bool cmp(const int * s,const int a,const int b,const int l)
{
return s[a]==s[b] && s[a+l]==s[b+l];
} int* Get_SA(const int n,int m)
{
int i,j,_p,*x=A,*y=B;
for(i=;i<m;++i)U[i]=;
for(i=;i<n;++i)U[x[i]=str[i]]++;
for(i=;i<m;++i)U[i]+=U[i-];
for(i=n-;i>=;--i)SA[--U[x[i]]]=i; for(j=,_p=;_p<n;m=_p,j<<=)
{
for(_p=,i=n-j;i<n;++i)y[_p++]=i;
for(i=;i<n;++i)if(SA[i]>=j)y[_p++]=SA[i]-j;
for(i=;i<n;++i)Tmp[i]=x[y[i]];
for(i=;i<m;++i)U[i]=;
for(i=;i<n;++i)U[Tmp[i]]++;
for(i=;i<m;++i)U[i]+=U[i-];
for(i=n-;i>=;--i)SA[--U[Tmp[i]]]=y[i];
for(swap(x,y),_p=,x[SA[]]=,i=;i<n;++i)
x[SA[i]]=cmp(y,SA[i-],SA[i],j)?_p-:_p++;
}
return x;
} long long Calc(int l,int r,const int n)
{
l=(l-)>>,r=(r-)>>;
int pos=Rank[l],L,R,temp=; L=,R=pos; while(L<R-)
{
int mid=L+((R-L)>>);
if(Query(mid+,pos)>=r-l+)R=mid;
else L=mid;
} temp+=pos-R;
L=pos,R=n+; while(L<R-)
{
int mid=L+((R-L)>>);
if(Query(pos+,mid)>=r-l+)L=mid;
else R=mid;
}
temp+=L-pos;
return (long long)temp*(r-l+);
} void Manacher(const int n)
{
int i,pos=;
for(i=n-;i>=;--i)
{
str[i+i+]=str[i];
str[i+i+]='#';
}
str[]='^';str[n<<|]='#';str[(n+)<<]='$';
for(i=;i<=(n<<|);++i)
{
if(p[pos]+pos>i)
p[i]=min(p[(pos<<)-i],p[pos]+pos-i);
else p[i]=;
while(str[i-p[i]]==str[i+p[i]])
{ if(i+p[i]>p[pos]+pos) Ans=max(Ans,Calc(i-p[i],i+p[i],n)); p[i]++; }
if(pos+p[pos]<i+p[i])pos=i;
} return ;
} int main()
{
int n; scanf("%s",str); n=strlen(str);
Rank=Get_SA(n+,);
Get_H(n);
Manacher(n); printf("%lld",Ans); return ;
}

[APIO2014] [Uoj103] [Bzoj3676] Palindromes回文串 [Manacher,后缀数组]的更多相关文章

  1. [APIO2014]回文串 manacher 后缀数组

    题面:洛谷 题解: 还是这个性质:对于每个串而言,本质不同的回文串最多只有O(n)个. 所以我们先求出这O(n)个本质不同的回文串,然后对整个串求一次sa. 然后对于每个回文串,求出它的出现次数,更新 ...

  2. [bzoj3676][Apio2014]回文串——Manacher+后缀自动机+倍增

    Brief Description 一个回文串的value定义为这个回文串的长度乘以出现次数.给定一个字符串,求\(value_{max}\). Algorithm Design 我们使用Manach ...

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

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

  4. [BZOJ3676][APIO2014]回文串(Manacher+SAM)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 3097  Solved: 1408[Submit][Statu ...

  5. BZOJ3676 APIO2014 回文串 Manacher、SA

    传送门 首先一个结论:串\(S\)中本质不同的回文串个数最多有\(|S|\)个 证明考虑以点\(i\)结尾的所有回文串,假设为\(S[l_1,i],S[l_2,i],...,S[l_k,i]\),其中 ...

  6. [Bzoj3676][Apio2014]回文串(后缀自动机)(parent树)(倍增)

    3676: [Apio2014]回文串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 3396  Solved: 1568[Submit][Statu ...

  7. 2018.12.15 bzoj3676: [Apio2014]回文串(后缀自动机)

    传送门 对原串建立一个后缀自动机,然后用反串在上面匹配. 如果当前匹配的区间[l,r][l,r][l,r]包裹了当前状态的endposendposendpos中的最大值,那么[l,maxpos][l, ...

  8. 【回文串-Manacher】

    Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 转:http://blog.sina.com.c ...

  9. BZOJ 2342 回文串-Manacher

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2342 思路:先跑一遍Manacher求出p[i]为每个位置为中心的回文半径,因为双倍回文串 ...

随机推荐

  1. bzoj1607 [Usaco2008 Dec]Patting Heads 轻拍牛头——暴力

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1607 观察一下数据范围,就是纯粹的暴力. 代码如下: #include<iostrea ...

  2. php排序函数测试

    1.sort,asort,arsort函数 十万个数的数组排序,用了0.17秒 $starttime=explode(' ',microtime());;for ($i=0; $i <10000 ...

  3. bzoj1036 树的统计(树链剖分+线段树)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 15120  Solved: 6141[Submit ...

  4. akka设计模式系列-Aggregate模式

    所谓的Aggregate模式,其实就是聚合模式,跟masterWorker模式有点类似,但其出发点不同.masterWorker模式是指master向worker发送命令,worker完成某种业务逻辑 ...

  5. vagrant使用centos的环境安装..

    vagrant这货挺好用的..简要就是, 下好virtualbox, vagrant, 然后下个你需要的box. 然后vagrant box add boxname boxpath就行. 然后在合适的 ...

  6. 取消安卓listview,scrollview,gridview滑动时候边缘模糊问题

    只需在xml文件里面声明: android:faddingEdge = "none" android:faddingEdgelenth = "0dp" andr ...

  7. 4CSS颜色和背景

    ---------------------------------------------------------------------------------------------------- ...

  8. Android 在fragment中实现返回键单击提醒 双击退出

    尝试用mvp架构加dagger2来重写了一下,大致功能都实现了,还没有全部完成. 项目地址 接近完成的时候,想在天气信息页面实现一个很常见的功能,也就是点击屏幕下方的返回键的时候不是返回到上一个act ...

  9. Android开发初体验

    本文通过开发一个应用来学习Android基本概念及构成应用的UI组件. 开发的应用名叫GeoQuiz,它能给出一道道地理知识问题.用户点击true或false按钮回答问题,应用即时做出反馈 第一步请先 ...

  10. win32窗口映射(部分)

    先理解一下“窗口”与“视区”的概念.“窗口”是逻辑坐标下的矩形区域,“视区”是设备坐标系下的区域.根据“窗口”和“视区”的大小可以确定x方向和y方向的比例因子. 例子如下: VOID OnPaint( ...