Manacher思想 SCOI2013 密码
关于$\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——凯撒密码和三重DES加解密
实验目的 1.完成第一个入门加解密--凯撒密码 2.完成当下较为流行的三重DES加解密技术 3.熟悉所学的实际运用方向 实验准备 硬件:计算机或笔记本电脑 操作系统:Mac操作系统 IDE环境:Ecl ...
- 密码泛在化实践者之路
密码泛在化实践者之路 嘉宾:周俊,曾任中国电子科技集团第三十研究所研究室主任.长期从事网络安全.信息保密相关技术和产品的研究,牵头和参与多个国家重大课题的研究工作,并拥有多项发明专利,曾获密码科学技术 ...
- 【数据结构】Manacher算法
Manacher Manacher算法要解决的问题是在一个字符串中寻找最大回文子字符串长度. 该问题的暴力解法是遍历每一个字符,从该字符向两边扩展,寻找边界. 但该方法中,每次扩展得到的信息并不能被充 ...
- 2019纪中暑假游记+总结
Travels总篇\texttt{Travels总篇}Travels总篇 7/4\texttt{7/4}7/4 下午才去纪中,早上就一大早和同学出去玩,看了蜘蛛侠然后到3点多才出发. 因为走南沙大桥所 ...
- 一句话题解(20170801~20170125)
8.1 bzoj 4720 noip2016 换教室 floyd预处理+期望(薛定谔的猫) bzoj 4318 OSU! 三次函数期望值 从一次.二次推得 8.2 bzoj 1076 状压+期望DP ...
- CSP-S集训刷题记录
$ CSP.S $ 集训刷题记录: $ By~wcwcwch $ 一.字符串专题: 1. [模板]$ manacher $ 算法 模型: 求出字符串 $ S $ 中所有回文串的位置及长度. $ sol ...
- 一句话题解(20180210~)
2.9 BZOJ 2006 [NOI2010]超级钢琴.这道题目几天之前就做了.做法是固定右端点,左端点在ST表上走,走法其实就是笛卡尔树的走法.完结撒花! BZOJ 1218 [HNOI2003]激 ...
- 退役前的做题记录2.0
退役前的做题记录2.0 最近在刷省选题......大致上是按照省份刷的. 不过上面的题目顺序是按照写题的顺序排列的,所以可能会有点乱哈. [BZOJ2823][AHOI2012]信号塔 最小圆覆盖,随 ...
- 和各路巨佬の随机挑战3总结
第三次挑战\huge \texttt{\color{purple}第\color{blue}三\color{green}次\color{block}挑\color{red}战}第三次挑战 规则 随机挑 ...
最新文章
- 孩子、老人与海豚,如何用 AI 伴他们走出孤独
- 写文献综述的二十八个要点
- 记一次内存泄漏问题的排查经历
- 《深入理解Elasticsearch(原书第2版)》一2.2 查询改写
- 手机端校验的那些事情(简单实例)
- linux操作系统学什么,Linux学习-第一天-什么是操作系统
- c语言中错误c2228,错误:C2228:''必须有class/struct/union
- Python | threading05 - 使用有界信号量,实现线程间同步
- 系统分析和设计方法之可行性分析和系统方案建议
- 数学建模——线性规划篇
- 移动开发之三种近场通信
- python就业前景不好_Python就业发展前景分析
- 强化学习代码 (肖志清)部分
- 触摸按键PCB设计要点
- 栈和队列、堆、堆栈的区别?
- Java多线程——什么是线程安全和线程不安全
- 苹果手机登录王者荣耀服务器未响应,王者荣耀服务器未响应怎么办?登陆未响应解决方法...
- 学人工智能数学要好吗?
- Android中Parcelable接口的应用
- 2022年材料员-岗位技能(材料员)考试题库及模拟考试
热门文章
- 手算梯度下降法,详解神经网络迭代训练过程
- 证券期货经营机构私募资产管理业务管理办法 2018年10月22日
- 重磅 | 消灭所有马赛克,谷歌宣布机器学习图像锐化工具RAISR
- RT-Thread Studio中ST-LINK下载报错“Old ST-LINK firmware version“解决
- C#通过函数名字符串执行相应的函数
- OpenGL-入门-BMP像素图glDrawPixels
- springboot源码解析,kafkaredis面试题
- 终于拿到了阿里2023年度九大Java技术文档——面试题+文档+白皮书
- VUE+ ELEMENT 选人的弹窗组件
- 华硕x580nv拆机_华硕x580nv拆机_做工扎实用料足 华硕S56超极本拆解图