题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068

题意:求一个字符串的最长回文子串

思路:

  • 枚举子串的两个端点,根据回文串的定义来判断其是否是回文串并更新答案,复杂度O(N3)。
  • 枚举回文串的对称轴i,以及回文半径r,由i和r可确定一个子串,然后暴力判断即可。复杂度O(N2)。
  • 在上一步的基础上,改进判断子串是否是回文串的算法。记fi(r)=(bool)以i为对称轴半径为r的子串是回文串,fi(r)的值域为{0, 1},显然fi(r)是关于r的单调函数,于是可以二分r,然后用字符串hash在O(1)的时间内判断子串是否是回文串,总复杂度O(NlogN)。
  • 虽然O(NlogN)的复杂度已经非常不错了,但还有线性的算法---Manacher算法。

Manacher算法:维护两个值r和id,r是以前的回文串的最大右边界,id是其对应的下标,如果当前考虑的对称轴i小于等于r,那么从i到r这一段子串是否可以和i左边的子串构成回文串(或者说最长能有多长)其实在之前是已经计算过了的(或者说计算出了一部分),因为将i作关于id的对称点i'=2*id-i,就不难发现i'周围若干字符和i周围若干字符是对应相同的,这是Manacher算法的核心之处,可以用i'的最大回文半径来更新i的最大回文半径,利用这个性质就能做到线性的复杂度。

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#pragma comment(linker, "/STACK:10240000")
#include <bits/stdc++.h>
using namespace std; #define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(a) (a).begin(), (a).end()
#define fillchar(a, x) memset(a, x, sizeof(a)) typedef long long ll;
typedef pair<int, int> pii; #ifndef ONLINE_JUDGE
namespace Debug {
void print(){cout<<endl;}template<typename T>
void print(const T t){cout<<t<<endl;}template<typename F,typename...R>
void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>
void print(T*p, T*q){int d=p<q?:-;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}
}
#endif // ONLINE_JUDGE
template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}
template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}
/* -------------------------------------------------------------------------------- */ const int maxn = 3e5 + ; /** 求字符串每个位置的最大回文半径,在字符串中找最长回文子串 **/
struct Manacher {
int p[maxn];/** 回文半径 **/
char s[maxn];
void init(char str[]) {
strcpy(s, str);
int n = strlen(s);
s[n * + ] = ;
for (int i = n * ; i; i -= ) {
s[i] = '#';
s[i - ] = s[i / - ];
}
s[] = '#';
}
/** 求每个点的最大回文半径 **/
void work() {
int r = , id = ;
p[] = ;
for (int i = ; s[i]; i ++) {
p[i] = i <= r? min(r - i + , p[ * id - i]) : ;
if (p[i] >= r - i + ) {
r = (id = i) + p[i] - ;
while ( * i - r - >= && s[r + ] == s[ * i - r - ]) {
r ++;
p[i] ++;
}
}
}
}
/** 求最长回文串的长度 **/
int solve() {
work();
int ans = ;
for (int i = ; s[i]; i ++) {
ans = max(ans, p[i] - );
}
return ans;
}
};
Manacher solver; char s[maxn]; int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
#endif // ONLINE_JUDGE
while (~scanf("%s", s)) {
solver.init(s);
printf("%d\n", solver.solve());
}
return ;
}

[hdu3068 最长回文]Manacher算法,O(N)求最长回文子串的更多相关文章

  1. Manacher算法 O(n) 求最长回文子串

    转自:http://bbs.dlut.edu.cn/bbstcon.php?board=Competition&gid=23474 其实原文说得是比较清楚的,只是英文的,我这里写一份中文的吧. ...

  2. HDU3068 最长回文 Manacher算法

    Manacher算法是O(n)求最长回文子串的算法,其原理很多别的博客都有介绍,代码用的是clj模板里的,写的确实是异常的简洁,现在的我只能理解个大概,下面这个网址的介绍比较接近于这个模板,以后再好好 ...

  3. hdu 3068 最长回文 manacher算法(视频)

    感悟: 首先我要Orz一下qsc,我在网上很难找到关于acm的教学视频,但偶然发现了这个,感觉做的很好,链接:戳戳戳 感觉这种花费自己时间去教别人的人真的很伟大. manacher算法把所有的回文都变 ...

  4. hdu_3068 最长回文(Manacher算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3068 最长回文 Time Limit: 4000/2000 MS (Java/Others)    M ...

  5. hdu-3068-最长回文(manacher算法模板)

    题目链接 /* Name:hdu-3068-最长回文 Copyright: Author: Date: 2018/4/24 16:12:45 Description: manacher算法模板 */ ...

  6. [算法] Manacher算法线性复杂度内求解最长回文子串

    参考:http://www.felix021.com/blog/read.php?2040 以上参考的原文写得很好,解析的非常清楚.以下用我自己的理解,对关键部分算法进行简单的描述: 回文的判断需要完 ...

  7. HDU 3068 最长回文 Manacher算法

    Manacher算法是个解决Palindrome问题的O(n)算法,能够说是个超级算法了,秒杀其它一切Palindrome解决方式,包含复杂的后缀数组. 网上非常多解释,最好的解析文章当然是Leetc ...

  8. HDU 3068 最长回文 manacher 算法,基本上是O(n)复杂度

    下面有别人的比较详细的解题报告: http://wenku.baidu.com/view/3031d2d3360cba1aa811da42.html 下面贴我的代码,注释在代码中: #include ...

  9. 字符串-回文-Manacher算法

    http://blog.csdn.net/zzkksunboy/article/details/72600679 https://segmentfault.com/a/1190000008484167 ...

随机推荐

  1. Mac os Pycharm 中使用Stanza进行实体识别(自然语言处理nlp)

    stanza 是斯坦福开源Python版nlp库,对自然语言处理有好大的提升,具体好在哪里,官网里面都有介绍,这里就不翻译了.下面放上对应的官网和仓库地址. stanza 官网地址:点击我进入 sta ...

  2. v&n赛 ML 第一步(python解决)

    题目链接 给了70组x,y,根据提示,是求拟合曲线,再通过x求y 知道MATLAB应该录入就能解决吧,但是没下这软件,试试用python解决 #coding:utf- from pwn import ...

  3. Springboot:thymeleaf模板(八)

    存放位置:resources\templates 访问方式:通过Controller请求访问,不可直接访问(相当于web项目的WEB-INF目录) 环境依赖: <!--thymeleaf模板支持 ...

  4. ES6中对函数的扩展

    ES6一路扩展,字符串.数组.数值.对象无一“幸免”,ES6说要雨露均沾,函数也不能落下,今天,就来讲解ES6对函数的扩展. 参数的默认值 在开发中,给函数的参数指定默认值,是很普遍很常见的一个需求, ...

  5. DiskPart.exe and managing Virtual Hard Disks (VHDs) in Windows 7

    coreygoOctober 7, 2009 In Windows 7, new commands have been added in DiskPart to allow for the creat ...

  6. java关于throw Exception的一个小秘密

    目录 简介 throw小诀窍 总结 java关于throw Exception的一个小秘密 简介 之前的文章我们讲到,在stream中处理异常,需要将checked exception转换为unche ...

  7. 从Spring迁移到Spring Boot

    文章目录 添加Spring Boot starters 添加应用程序入口 Import Configuration和Components 迁移应用程序资源 迁移应用程序属性文件 迁移Spring We ...

  8. eclipse 创建maven项目失败

    问题描述: eclipse 初次创建maven项目报错 可能是maven-archetype-quickstart:1.1.jar 包失效了或者没有? 有人说把这个jar包放在maven本地仓库里 我 ...

  9. CSS开发技巧(三):图片点击缩放

    前言  利用CSS实现图片的点击缩放是一个很值得研究的效果.在某些业务需求场景中,我们可能并没有足够的空间展示过大的图片,这就需要限制图片容器的宽度和高度.然而图片限制了宽度,一些图片的细节便又无法看 ...

  10. Linux 搭建nginx的PID

    pid logs/nginx.pid 安装的时候就是没有,其实在启动 nginx 时自动生成的 里面存放的是 当前 nginx 住进程的 ID 号:所以在配置文件中指定pidpid /usr/loca ...