题目链接: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. .NET Core 发布时去掉多余的语言包文件夹

    用 .NET Core 3.x 作为目标框架时发布完之后,会发现多了很多语言包文件夹,类似于: 有时候,不想要生成这些语言包文件夹,需要稍微配置一下. 在 PropertyGroup 节点中添加如下的 ...

  2. selenium获取多窗口句柄并一切换至原窗口句柄(三个窗口)

    网上有很多是selenium基于python来获取两个窗口句柄与切换,本文实现用python+selenium获取多窗口句柄并一一切换至原窗口句柄(三个窗口),且在每个窗口下进行一个搜索或翻译,然后截 ...

  3. 操作google_sheets

    起源:最近了使用flask和bootstrap写了测试小工具,数据全部使用excel存储,部署到测试环境. 问题:每次每个人在使用excel数据时都需要重新编辑好的excel通过upload按钮传到服 ...

  4. [YII2.0] 高级模板简单安装教程

    YIICHINA官网教程就很完善:http://www.yiichina.com/tutorial/692 但是在yii2框架安装运行init.bat报错php.exe不是内部或外部命令, 解决办法: ...

  5. 深拷贝、浅拷贝与Cloneable接口

    深拷贝与浅拷贝 浅拷贝 public class Student implements Cloneable{ Integer a; Integer b; @Override protected Obj ...

  6. windows服务程序的编写

    服务编写https://blog.csdn.net/lanuage/article/details/77937407 #include <windows.h> #include <s ...

  7. Node.js快速创建一个访问html文件的服务器

    var http = require('http'), // 引入需要的模块 fs = require('fs'), //引入文件读取模块 cp = require('child_process'), ...

  8. iOS开发·runtime原理与实践: 消息转发篇(Message Forwarding) (消息机制,方法未实现+API不兼容奔溃,模拟多继承)...

    本文Demo传送门: MessageForwardingDemo 摘要:编程,只了解原理不行,必须实战才能知道应用场景.本系列尝试阐述runtime相关理论的同时介绍一些实战场景,而本文则是本系列的消 ...

  9. 开发常见错误解决(6)WSE3.0未处理的WebException,未处理的Web异常,基础连接以及关闭...

    开发常见错误解决(6)WSE3.0未处理的WebException,未处理的Web异常,基础连接以及关闭. 我们在调试WSE服务端服务的时候会抛出,未处理的Web异常,基础连接以及关闭的异常信息.如图 ...

  10. 题目分享Y

    题意:给出一个n个点n条边的图且不一定连通(原题面为每个节点出度为1),相邻节点不能同时被选,每个节点有其对应价值,求最多能获得多少价值?n<=1e6,val[i]<=1e6 分析:很容易 ...