关于$\mathrm{Manacher}$算法,网上介绍已经很全面 这里说一下自己的理解

这里的$rad$数组:$rad_i$表示以以位置i为中心的最长回文串的回文半径(不包括i这个点)。

朴素的思想大概是从每个点出发像两边扩展,大概$O(n^2)$复杂度?据说$\mathrm{Manacher}$是$O(n)$的(不会证,Orz,大概因为每个位置只会被暴力扩展$O(1)$次)这是因为回文串有对称性,我们可以利用这点来优化算法。现在假设我们已经得到了$i$和$i$以前的$rad$值,现在想直接通过$O(1)$的时间计算出i右边一些点的$rad$值。设$k$从$1$到$rad_i$,表示现在想直接计算出$rad_{i+k}$的$rad$值。则有下列情况

其中

红色:$rad_i$
橙色:$rad_{i-k}$
绿色:$rad_{i-k}$

①$rad_i-k<rad_{i-k}$————————————————————————————————————————————————————————————

此时$rad_{i+k}$一定为$rad_i-k$否则根据对称性,$rad_i$可以更大。

②$rad_i-k>rad_{i-k}$————————————————————————————————————————————————————————————

此时根据对称性也可以很显然地看出$rad_{i+k}=rad_{i-k}$

由①②有,当$rad_i-k\not=rad_{i-k}$时,$rad_{i+k}=\min{\{rad_{i-k},rad_i-k\}}$

那么$rad_i-k=rad_{i+k}$时怎么办呢

③$rad_i-k=rad_{i-k}$————————————————————————————————————————————————————————————

这时即使$rad_{i+k}>rad_{i-k}$也没有矛盾,此时应当令i+=k用朴素的算法扩大$rad_i$之后再用这个$rad_i$迭代更新。

代码:

for(int i=1,j=0,k;i<=len;){for(;s[i-j-1]==s[i+j+1];j++);rad[i]=j;for(k=1;k<=j && rad[i]-k!=rad[i-k];k++)rad[i+k]=min(rad[i]-k,rad[i-k]);i+=k;j=max(j-k,0);
}

但是这样只能求出长度为奇数的回文串的长度,对于偶数,我们这样处理。

char s[Maxn]={0};
s[0]='*';
for(int i=0;i<_len;i++){s[++len]=_s[i];s[++len]='#';
}
s[len]='&';

之后再按上面的方法求即可。

然后这里再说一下$\mathrm{SCOI2013}$的密码,用了$\mathrm{Manacher}$的思想。(题目链接http://acm.uestc.edu.cn/#/problem/show/128)

很容易想到朴素的算法,把必须为相同字符的合并为一个集合(用并查集实现),然后对必须不相同的集合连边,从集合向集合中的元素连边。后一步是$O(n)$的,而前一步最坏是$O(n^2)$对于$10^5$的数据显然无法承受,这里很自然想到$\mathrm{Manacher}$的$O(n)$

$i$从$1$开始,维护$rad_i+i$的最大值,为$MX_r$,这样的$i$记为$MX_{id}$,然后显然我们只需要从$i+\max{\{0, \min{\{MX_r-i,rad_{2MX_{id}-i}\}}\}}$开始合并,大概又是$O(n)$的

完整代码

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#define dout printf
using namespace std;const int Maxn=100000+10;
int n,rad[Maxn*2];
int col[Maxn*2],cannot[Maxn*2][30],cnt=0;
int stk[30],top;
bool instk[Maxn*2];
inline void getint(int&x){char c=getchar();for(x=0;!isdigit(c);c=getchar());for(;isdigit(c);c=getchar())x=x*10+c-'0';
}
struct Edge{int b;Edge*next;}edges[Maxn*3*2],*firc[Maxn*2],*fird[Maxn*2];int tot;
void AddEdge(int a,int b,Edge*fir[]){edges[++tot]=(Edge){b,fir[a]};fir[a]=edges+tot;
}
int fa[Maxn*2];
int Find(const int&x){return fa[x]==x?x:fa[x]=Find(fa[x]);
}
bool Union(int x,int y){x=Find(x),y=Find(y);if(x==y)return 0;return fa[y]=x,1;
}
void input(){getint(n);for(int i=1;i<=n;i++)getint(rad[(i<<1)-1]);for(int i=1;i<n;i++)getint(rad[i<<1]);
}void work(const int n2=n*2){int MX_r=1,MX_id=1;char*ans=new char[Maxn];memset(ans,0,sizeof(*ans)*Maxn);for(int i=1;i<=n2;i++)fa[i]=i;for(int i=2;i<=n2;i++){for(int j=max(0, min(MX_r-i,rad[MX_id*2-i]) );i-j>0&&i+j<=n2&&j<=rad[i];j++) {Union(i-j,i+j);}if(rad[i]+i>MX_r)MX_r=i+rad[i],MX_id=i;}for(int f,i=1;f=Find(i),i<=n2;i+=2)AddEdge(f,(i+1)>>1,firc);for(int f1,f2,d,i=2;i<=n2;i++){d=rad[i]+1;f1=Find(i-d),f2=Find(i+d);AddEdge(f1,f2,fird);AddEdge(f2,f1,fird);}for(int x,real,f,i=1;real=(i+1)>>1,i<=n2;i+=2)if(!ans[real]){x=1;f=Find(i);for(;cannot[f][x];x++);for(Edge*p=fird[f];p;p=p->next)cannot[p->b][x]=1;for(Edge*p=firc[f];p;p=p->next)ans[p->b]=x+'a'-1;}puts(ans+1);delete ans;
}
int main(){freopen("password.in","r",stdin);freopen("password.out","w",stdout);input();work();return 0;
}

转载于:https://www.cnblogs.com/showson/p/4301627.html

Manacher思想 SCOI2013 密码相关推荐

  1. 密码学入门1——凯撒密码和三重DES加解密

    实验目的 1.完成第一个入门加解密--凯撒密码 2.完成当下较为流行的三重DES加解密技术 3.熟悉所学的实际运用方向 实验准备 硬件:计算机或笔记本电脑 操作系统:Mac操作系统 IDE环境:Ecl ...

  2. 密码泛在化实践者之路

    密码泛在化实践者之路 嘉宾:周俊,曾任中国电子科技集团第三十研究所研究室主任.长期从事网络安全.信息保密相关技术和产品的研究,牵头和参与多个国家重大课题的研究工作,并拥有多项发明专利,曾获密码科学技术 ...

  3. 【数据结构】Manacher算法

    Manacher Manacher算法要解决的问题是在一个字符串中寻找最大回文子字符串长度. 该问题的暴力解法是遍历每一个字符,从该字符向两边扩展,寻找边界. 但该方法中,每次扩展得到的信息并不能被充 ...

  4. 2019纪中暑假游记+总结

    Travels总篇\texttt{Travels总篇}Travels总篇 7/4\texttt{7/4}7/4 下午才去纪中,早上就一大早和同学出去玩,看了蜘蛛侠然后到3点多才出发. 因为走南沙大桥所 ...

  5. 一句话题解(20170801~20170125)

    8.1 bzoj 4720 noip2016 换教室 floyd预处理+期望(薛定谔的猫) bzoj 4318 OSU! 三次函数期望值 从一次.二次推得 8.2 bzoj 1076 状压+期望DP ...

  6. CSP-S集训刷题记录

    $ CSP.S $ 集训刷题记录: $ By~wcwcwch $ 一.字符串专题: 1. [模板]$ manacher $ 算法 模型: 求出字符串 $ S $ 中所有回文串的位置及长度. $ sol ...

  7. 一句话题解(20180210~)

    2.9 BZOJ 2006 [NOI2010]超级钢琴.这道题目几天之前就做了.做法是固定右端点,左端点在ST表上走,走法其实就是笛卡尔树的走法.完结撒花! BZOJ 1218 [HNOI2003]激 ...

  8. 退役前的做题记录2.0

    退役前的做题记录2.0 最近在刷省选题......大致上是按照省份刷的. 不过上面的题目顺序是按照写题的顺序排列的,所以可能会有点乱哈. [BZOJ2823][AHOI2012]信号塔 最小圆覆盖,随 ...

  9. 和各路巨佬の随机挑战3总结

    第三次挑战\huge \texttt{\color{purple}第\color{blue}三\color{green}次\color{block}挑\color{red}战}第三次挑战 规则 随机挑 ...

最新文章

  1. 孩子、老人与海豚,如何用 AI 伴他们走出孤独
  2. 写文献综述的二十八个要点
  3. 记一次内存泄漏问题的排查经历
  4. 《深入理解Elasticsearch(原书第2版)》一2.2 查询改写
  5. 手机端校验的那些事情(简单实例)
  6. linux操作系统学什么,Linux学习-第一天-什么是操作系统
  7. c语言中错误c2228,错误:C2228:''必须有class/struct/union
  8. Python | threading05 - 使用有界信号量,实现线程间同步
  9. 系统分析和设计方法之可行性分析和系统方案建议
  10. 数学建模——线性规划篇
  11. 移动开发之三种近场通信
  12. python就业前景不好_Python就业发展前景分析
  13. 强化学习代码 (肖志清)部分
  14. 触摸按键PCB设计要点
  15. 栈和队列、堆、堆栈的区别?
  16. Java多线程——什么是线程安全和线程不安全
  17. 苹果手机登录王者荣耀服务器未响应,王者荣耀服务器未响应怎么办?登陆未响应解决方法...
  18. 学人工智能数学要好吗?
  19. Android中Parcelable接口的应用
  20. 2022年材料员-岗位技能(材料员)考试题库及模拟考试

热门文章

  1. 手算梯度下降法,详解神经网络迭代训练过程
  2. 证券期货经营机构私募资产管理业务管理办法 2018年10月22日
  3. 重磅 | 消灭所有马赛克,谷歌宣布机器学习图像锐化工具RAISR
  4. RT-Thread Studio中ST-LINK下载报错“Old ST-LINK firmware version“解决
  5. C#通过函数名字符串执行相应的函数
  6. OpenGL-入门-BMP像素图glDrawPixels
  7. springboot源码解析,kafkaredis面试题
  8. 终于拿到了阿里2023年度九大Java技术文档——面试题+文档+白皮书
  9. VUE+ ELEMENT 选人的弹窗组件
  10. 华硕x580nv拆机_华硕x580nv拆机_做工扎实用料足 华硕S56超极本拆解图