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 ...
随机推荐
- python 路径
atm---main.py import os ,sys print(__file__) print(os.path.abspath(__file__))#绝对路径 print(os.path.dir ...
- 发现一个jq的问题
用jq对checkbox的checked属性进行操作时,使用$(‘#id’).attr(‘checked’, true);竟然无效,改成$(‘#id’).prop(‘checked’, true);才 ...
- Java基础知识点
以下10点为JAVA 基础知识,后面将足以总结和完善以备面试 数据类型 (包装类,字符串,数组) 异常处理 Java IO和NIO 数据结构 (集合和容器 ) 多线程(并发) 网络通信(协议) 面向对 ...
- Poj(2679),SPFA,邻接表(主流写法)
题目链接:http://poj.org/problem?id=3268 题意: 有编号为1-N的牛,它们之间存在一些单向的路径.给定一头牛的编号,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求 ...
- MySQL 数据库发展历程及缺点
传统关系数据库的瓶颈 传统的关系数据库具有不错的性能,高稳定型,久经历史考验,而且使用简单,功能强大,同时也积累了大量的成功案例.在互联网领域,MySQL成为了绝对靠前的王者,毫不夸张的说,MySQL ...
- ubuntu配置服务器环境
今天环境不知道怎么就不能用了.自己新配了一个: 添加源: vi /etc/apt/sources.list 将下面这些源添加进去: deb http://debian.ustc.edu.cn/ubun ...
- Codeforces Round #260 (Div. 2) B
Description Fedya studies in a gymnasium. Fedya's maths hometask is to calculate the following expre ...
- 实现的时钟(time)
<!doctype html><html lang="en"><head> <script type="text/javascr ...
- linux(centos)下SVN服务器如何搭建
检测是否符合pptp的搭建环境的要求 使用下面的指令: 123 cat /dev/net/tun如果这条指令显示结果为下面的文本,则表明通过:cat: /dev/net/tun: File descr ...
- FragMent 初级学习
FragMent 可以用在一个Activity中也可以用在多个Activity中 我们在activity中加载FragMent的时候,首先添加一个myFragMent的类 通过onCreateView ...