Manacher 算法(hdu 3068 && hdu 3294)
今天打算补前晚 BC 的第二题,发现要用到能在 O(n) 时间求最大回文子串长度的 Manacher 算法,第一次听,于是便去百度了下,看了大半天,总算能看懂了其思想,至于他给出的代码模板我没能完全看懂,只好自己试着实现,发现理解了思想后还是能实现出来的,用自己的风格去写更好理解,先附上讲解 Manacher 算法的几个链接:
Manacher算法--O(n)回文子串算法 (我就是看这个理解的~)
hdu 3068 正好是裸题,我便试着写下,我是这样子构造新串的:

hdu 3068 代码如下:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = ; // str 为原串, s 为新串
char str[N], s[N << ];
int p[N << ];
// p[i] 表示以 s[i] 为中心时的回文半径,不包括 p[i]
// 即若 s[i - 1] != s[i + 1] 时,p[i] = 0; int main() {
while(~scanf("%s",str)) {
int n = strlen(str);
s[] = '$'; // 构造新串
s[] = '#';
for(int i = ; i < n; ++i) {
s[i * + ] = str[i]; // 下标要处理好
s[i * + ] = '#';
}
n = n * + ; // 更新新串的长度
s[n] = '\0'; // 最后的结束符别忘了 // right 记录的是在 i 之前的回文串中,某个回文串延伸至最右端的位置
// id 就是该回文串的下标(注意都是在新串中的)
int right = , id = ;
p[] = ;
// 因为是 s[0] == '$',作为特殊标记,左右两边都没有相等的,所以初始化为 0,
// 同理 right 一开始能延伸到的位置就是 s[0] 的位置,也就是 0,id 当然也为 0 // 主算法要开始了
for(int i = ; i < n; ++i) {
if(right > i)
p[i] = min(p[ * id - i], right - i);
else p[i] = ;
while(s[i + p[i] + ] == s[i - p[i] - ]) ++p[i];
if(i + p[i] > right) {
right = i + p[i];
id = i;
}
} // printf("\n下标: ");
// for(int i = 0; i <= n; ++i)
// printf("%d ",i);
// puts("");
// printf("新串: ");
// for(int i = 0; i < n; ++i)
// printf("%c ",s[i]);
// printf(" \\0\np[i]: ");
// for(int i = 0; i < n; ++i)
// printf("%d ",p[i]);
// puts(""); int ans = ;
for(int i = ; i < n; ++i)
ans = max(ans, p[i]); // p[i] 就是原串中的回文长度, 无须作任何 +1、-1
printf("%d\n",ans);
}
return ;
}
还有一题也是需要用到这个算法的,hdu 3294,只是对于最后的结果输出需要处理一下,恶心的模拟,直接贴代码了:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = ; char str[N], s[N << ];
int p[N << ]; int main() {
while(gets(str)) {
int n = strlen(str);
s[] = '$';
s[] = '#';
for(int i = ; i < n; ++i) {
s[i * - ] = str[i];
s[i * - ] = '#';
}
n = n * - ;
s[n] = '\0'; int right = , id = ;
p[] = ;
for(int i = ; i < n; ++i) {
if(right > i)
p[i] = min(p[id * - i], right - i);
else p[i] = ;
while(s[i + p[i] + ] == s[i - p[i] - ]) ++p[i];
if(i + p[i] > right) {
right = i + p[i];
id = i;
}
}
int Max = , mid;
for(int i = ; i < n; ++i) {
if(p[i] > Max) {
Max = p[i];
mid = i;
}
}
if(Max == ) {
puts("No solution!");
continue;
} int strid = (mid - Max + ) / + ;
printf("%d %d\n", strid - , strid - + Max - ); for(int i = ; i < Max; ++i) {
char ch = str[strid + i] + ('a'- str[]);
if(ch < 'a') ch = 'z' + - ('a' - ch);
else if(ch > 'z') ch = 'a' - + (ch - 'z');
printf("%c",ch);
}
puts("");
}
return ;
}
Manacher 算法(hdu 3068 && hdu 3294)的更多相关文章
- hdu 3068 最长回文 manacher算法(视频)
感悟: 首先我要Orz一下qsc,我在网上很难找到关于acm的教学视频,但偶然发现了这个,感觉做的很好,链接:戳戳戳 感觉这种花费自己时间去教别人的人真的很伟大. manacher算法把所有的回文都变 ...
- HDU 3068:最长回文(Manacher算法)
http://acm.hdu.edu.cn/showproblem.php?pid=3068 最长回文 Problem Description 给出一个只由小写英文字符a,b,c...y,z组成的 ...
- hdu 3068 最长回文 (Manacher算法求最长回文串)
参考博客:Manacher算法--O(n)回文子串算法 - xuanflyer - 博客频道 - CSDN.NET 从队友那里听来的一个算法,O(N)求得每个中心延伸的回文长度.这个算法好像比较偏门, ...
- HDU 3068 最长回文 Manacher算法
Manacher算法是个解决Palindrome问题的O(n)算法,能够说是个超级算法了,秒杀其它一切Palindrome解决方式,包含复杂的后缀数组. 网上非常多解释,最好的解析文章当然是Leetc ...
- Hdu 3068 最长回文字串Manacher算法
题目链接 最长回文 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
- HDU - 3068 最长回文(manacher算法)
题意:给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 分析: manacher算法: 1.将字符串中每个字符的两边都插入一个特殊字符.(此操作的目的是,将字符串 ...
- hdu 3068 最长回文 manacher
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.回文就是正 ...
- HDU - 3068 最长回文 【Manacher】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=3068 思路 n^3 的做法 对于每个字符 同时 往左往右搜 但是要分奇偶 就是 n^3 n^2 的做法 ...
- HDU - 3068 最长回文(manacher)
HDU - 3068 最长回文 Time Limit: 2000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u Subm ...
随机推荐
- JavaScript中创建类,赋值给ajax中的data参数
缘由:因为要给根据是否选中checkbox来动态增加ajax中data的属性(ajax的data属性格式的几种方法,参考http://www.jb51.net/article/46676.htm) d ...
- 通过URl将服务器的图片下载到本地并压缩
private void downloadServerPic(final String url1) { new Thread() { @Override public void run() { // ...
- 鼠标放上去,div高度随文字增加,并显示剩余的文字。
/*这里是鼠标放上去显示全名 */ .kb2wText{display:block; height:20px; width:150px; line-height:20px; color:#0 ...
- 使用 Filter 完成一个简单的权限模型
****对访问进行权限控制: 有权限则可以访问, 否则提示: 没有对应的权限, 请 返回其访问者的权限可以在manager那进行设置:
- 使用存储过程来动态调用数据(SELECT)
USE [MyTestDb] GO /****** Object: StoredProcedure [dbo].[PROC_GetChannelList] Script Date: 04/09/201 ...
- pip命令使用国内pypi镜像源加速在线安装
参考:http://www.cnblogs.com/yudar/p/4444097.html 用easy_install和pip来安装第三方库很方便 它们的原理其实就是从Python的官方源pypi. ...
- common-pool2 使用
common-pool2提供了3中对象池管理方式,它们的使用方式基本一样,这里以GenericObjectPool对象池为例介绍其使用方式,一般实现自己的对象池需要经过2个步骤 1.实现PooledO ...
- Java根据条件删除Map中元素
今天在写程序过程中,需要根据判断条件删除一个Map中的相应数据,我自然而然想到可以通过调用Map中的remove(Object key)函数进行删除:代码如下: public Map<Doubl ...
- [kipmi0]进程导致系统负载高
最近一个用户这边服务器运行四五天就会出现服务器负载很高的情况,原本正常是0.3~0.5左右 不正常的时候会达到3,重启机器就正常,开始以为是程序问题,后来在观察的时候把程序给杀掉了 然后重启,结果负 ...
- java中的构造函数
在c++中就学习了构造函数,今天学习java又碰到了构造函数,重新写一篇博客来理解一下 其实直接听这个词并不能理解这是什么,但其实看了它的作用,就很好理解了 当创建一个对象时,往往需要做一些初始化工作 ...