最长回文子串(Manacher算法)
回文字符串,想必大家不会不熟悉吧?
回文串会求的吧?暴力一遍O(n^2)很简单,但当字符长度很长时便会TLE,简单,hash+二分搞定,其复杂度约为O(nlogn), 而Manacher算法能够在线性的时间内处理出最长回文子串。
让我们来看道题:http://acm.hdu.edu.cn/showproblem.php?pid=3068

这个算法的巧妙之处,便是把奇数的回文串和偶数的回文串统一起来考虑了。这一点一直是在做回文串问题中时比较烦的地方。这个算法还有一个很好的地方就是充分利用了字符匹配的特殊性,避免了大量不必要的重复匹配。那怎么去实现呢?
我们要求字符串s中最长的回文子串
Manacher重新构造了一个新数组,在每两个字符中间插入一个'#',如下图:

我们很容易发现,如果出现这种情况(如下图)在处理第三个字符('#')市,会发现扫到左侧时候可能会出现越界

为了避免索引数超出数组边界值做字符比较,可以在处理过的字符串的第一个位置(索引为0的位置)加入一个区分字符,笔者喜欢用'@'。

上图便是处理过的样子。(编号表示数组位数,3表示是s[3]的字符)
我们现在用p[i]数组表示以字符s[i]为中心的回文半径(如p[3] = 1)。
我们很容易发现最长子序列的长度刚好是(p[i] - 1)。
那么我们怎么来求p[i]数组呢?
步骤如下:
当处理到[i]的时候,我们去找0-i中是否存在一个数(设为id)使得p[id] + id > i,设mx = p[id] + id。

如上图,由于红的字符串是回文字符串,所以关于j对称的回文子串和关于i对称的回文子串是完全一样的(图中两段绿色的线条),而满足mx-i>P[j]时说明此时j的回文子串半径小于j到mx关于j对称的左端点的差,此时可以初始化P[i]=P[j]。但如果绿色部分超出id的回文串呢?
如下图:

紫色表示以j为中心的回文串超出以id为中心的回文半径的部分(即图中红色部分)由于红的字符串是回文字符串,所以关于j对称的回文子串和关于i对称的在mx和mx的对称点之间的回文子串是完全一样的(图中两段绿色的线条),而满足mx-i<=P[j]时说明此时j的回文子串半径大于或等于j到mx关于j对称的左端点的差,此时可以初始化P[i]=mx-i,超出部分只能一个个判断。再对P[i]的回文子串半径进行进一步的增大。(以上两图均取自参考论文)
综上所述初始化p[i] = min(p[j], mx - i);
对于超出回文字符串部分(即红色部分,我们只能一个一个的去判断)
即while(s[i + p[i]] == s[i - p[i]])p[i] += 1;
当mx <= i 的时候我们只能将p[i] 初始化为1(对于它都是未知的,只能通过一位一位去比较)。
附上总代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = + ; char s[N]; int p[N]; int n, id, mx; void work(){
id = mx = ;
int ans = ;
n = strlen(s);
for(int i = n; i >= ; i --){
s[ * i + ] = s[i];
s[ * i + ] = '#';
}
s[] = '@';
p[] = ;
for(int i = ; i < * n + ; i ++){
if(mx > i)p[i] = min(p[ * id - i], mx - i);
else p[i] = ;
while(s[i + p[i]] == s[i - p[i]]) p[i] += ;
if(mx < p[i] + i){
id = i;
mx = p[i] + i;
}
ans = max(ans, p[i] - );
}
printf("%d\n", ans);
} int main(){
while(scanf("%s", s) == )work();
return ;
}
参考资料:http://blog.csdn.net/pi9nc/article/details/9251455
最长回文子串(Manacher算法)的更多相关文章
- 九度OJ 1528 最长回文子串 -- Manacher算法
题目地址:http://ac.jobdu.com/problem.php?pid=1528 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"n ...
- lintcode最长回文子串(Manacher算法)
题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...
- 最长回文子串—Manacher 算法 及 python实现
最长回文子串问题:给定一个字符串,求它的最长回文子串长度.如果一个字符串正着读和反着读是一样的,那它就是回文串. 给定一个字符串,求它最长的回文子串长度,例如输入字符串'35534321',它的最 ...
- hihocoder #1032 : 最长回文子串 Manacher算法
题目链接: https://hihocoder.com/problemset/problem/1032?sid=868170 最长回文子串 时间限制:1000ms内存限制:64MB 问题描述 小Hi和 ...
- 5. Longest Palindromic Substring(最长回文子串 manacher 算法/ DP动态规划)
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- HiHo 1032 最长回文子串 (Manacher算法求解)
/** * 求解最长回文字串,Manacher算法o(n)求解最长回文子串问题 **/ #include<cstdio> #include<cstdlib> #include& ...
- hihoCoder #1032 : 最长回文子串 [ Manacher算法--O(n)回文子串算法 ]
传送门 #1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相 ...
- 51nod1089 最长回文子串 manacher算法
0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一个字符串正着读和反着读是一样的,那它就是回文串.下面是一些回文串的实例: 12321 a aba abba aaaa ...
- 最长回文子串Manacher算法模板
Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串.其算法的基本原理就是利用已知回文串的左半部分来推导右半部分. 首先,在字符串s中,用rad[i]表示第i个字符 ...
- 求最长回文子串——Manacher算法
回文串包括奇数长的和偶数长的,一般求的时候都要分情况讨论,这个算法做了个简单的处理把奇偶情况统一了.算法的基本思路是这样的,把原串每个字符中间用一个串中没出现过的字符分隔开来(统一奇偶),用一个数组p ...
随机推荐
- MongoDB学习笔记——集合管理
创建集合 使用db.createCollection(name, options) 方法创建集合 name 所创建的集合名称必选! options 可选.指定有关内存大小及索引的选项 db.creat ...
- Tomcat报java.lang.ClassNotFoundException: 1catalina.org.apache.juli.FileHandler
最近在生产环境部署Tomcat的时候,在启动的时候,在控制台报"java.lang.ClassNotFoundException: 1catalina.org.apache.juli.Fil ...
- nginx 做负载均衡
最近正在研究Nginx,Nginx作为反向代理服务器,可以对Web服务器提供加速,并且具有负载均衡的功能. 首先我要在官网下载Nginx(http://nginx.org/en/download.ht ...
- 大型文档源文件拆分编辑编译\include{filename}
大型文档,如果把所有的文字都录入在同一个.tex文件中,那个文件的体积是不可估量的,文件的结构式混乱不堪的,文字的定位也是令人头疼的.幸亏latex提供了结构化的处理命令---include. 命令\ ...
- String to Integer (atoi)
Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. ...
- linux下对2个连通的串口读写遇到的问题
想要分析下zmodem协议,搜索发现linux下的工具lrzsz是一个包含x,y,z modem传输的工具,下载其源码,下载.它可以借助各种串行的接口进行数据传输,比如串口,socket也可以,这点描 ...
- Oracle常用plsql
String aggr http://www.oracle-base.com/articles/misc/string-aggregation-techniques.php SELECT 'S ...
- Webpack+React+ES6入门指南[转]
React无疑是今年最火的前端框架,github上的star直逼30,000,基于React的React Native的star也直逼20,000.有了React,组件化似乎不再步履蹒跚,有了Reac ...
- 【温故而知新-Javascript】窗口效果 (全屏显示窗口、定时关闭窗口)
1.全屏显示窗口 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://ww ...
- UESTC 880 生日礼物 --单调队列优化DP
定义dp[i][j]表示第i天手中有j股股票时,获得的最多钱数. 转移方程有: 1.当天不买也不卖: dp[i][j]=dp[i-1][j]; 2.当天买了j-k股: dp[i][j]=max(dp[ ...