最长回文子串Manacher算法模板
Manacher算法能够在O(N)的时间复杂度内得到一个字符串以任意位置为中心的回文子串。其算法的基本原理就是利用已知回文串的左半部分来推导右半部分。
首先,在字符串s中,用rad[i]表示第i个字符的回文半径,即rad[i]尽可能大,且满足:
s[i-rad[i],i-1]=s[i+1,i+rad[i]]
很明显,求出了所有的rad,就求出了所有的长度为奇数的回文子串.
至于偶数的怎么求,最后再讲.
假设现在求出了rad[1..i-1],现在要求后面的rad值,并且通过前面的操作,得知了当前字符i的rad值至少为j.现在通过试图扩大j来扫描,求出了rad[i].再假设现在有个指针k,从1循环到rad[i],试图通过某些手段来求出[i+1,i+rad[i]]的rad值.
根据定义,黑色的部分是一个回文子串,两段红色的区间全等.
因为之前已经求出了rad[i-k],所以直接用它.有3种情况:
①rad[i]-k<rad[i-k]
如图,rad[i-k]的范围为青色.因为黑色的部分是回文的,且青色的部分超过了黑色的部分,所以rad[i+k]肯定至少为rad[i]-k,即橙色的部分.那橙色以外的部分就不是了吗?这是肯定的.因为如果橙色以外的部分也是回文的,那么根据青色和红色部分的关系,可以证明黑色部分再往外延伸一点也是一个回文子串,这肯定不可能,因此rad[i+k]=rad[i]-k.为了方便下文,这里的rad[i+k]=rad[i]-k=min(rad[i]-k,rad[i-k]).
②rad[i]-k>rad[i-k]
如图,rad[i-k]的范围为青色.因为黑色的部分是回文的,且青色的部分在黑色的部分里面,根据定义,很容易得出:rad[i+k]=rad[i-k].为了方便下文,这里的rad[i+k]=rad[i-k]=min(rad[i]-k,rad[i-k]).
根据上面两种情况,可以得出结论:当rad[i]-k!=rad[i-k]的时候,rad[i+k]=min(rad[i]-k,rad[i-k]).
注意:当rad[i]-k==rad[i-k]的时候,就不同了,这是第三种情况:
如图,通过和第一种情况对比之后会发现,因为青色的部分没有超出黑色的部分,所以即使橙色的部分全等,也无法像第一种情况一样引出矛盾,因此橙色的部分是有可能全等的,但是,根据已知的信息,我们不知道橙色的部分是多长,因此就把i指针移到i+k的位置,j=rad[i-k](因为它的rad值至少为rad[i-k]),等下次循环的时候再做了.
整个算法就这样.
至于时间复杂度为什么是O(n),我已经证明了,但很难说清楚.所以自己体会吧.
上文还留有一个问题,就是这样只能算出奇数长度的回文子串,偶数的就不行.怎么办呢?有一种直接但比较笨的方法,就是做两遍(因为两个程序是差不多的,只是rad值的意义和一些下标变了而已).但是写两个差不多的程序是很痛苦的,而且容易错.所以一种比较好的方法就是在原来的串中每两个字符之间加入一个特殊字符,再做.如:aabbaca,把它变成(#a#a#b#b#a#c#a#),左右的括号是为了使得算法不至于越界。这样的话,无论原来的回文子串长度是偶数还是奇数,现在都变成奇数了.
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int N=1e6+;
int rad[N<<];
char s[N],cpy[N<<];
void manacher(char *s,int len){
for(int i=,j=,k;i<len;i+=k){
while(s[i-j-]==s[i+j+])j++;
rad[i]=j;
for(k=;k<=rad[i]&&rad[i-k]!=rad[i]-k;k++){
rad[i+k]=min(rad[i-k],rad[i]-k);
}
j=max(j-k,);
}
}
void work(char *s){
int len=strlen(s)*+;
cpy[]='(';cpy[]='#';cpy[len-]=')';
for(int i=,j=;s[i];i++,j+=){
cpy[j]=s[i];
cpy[j+]='#';
}
manacher(cpy,len);
int ans=;
for(int i=;i<len;i++){
ans=max(ans,rad[i]);
}
printf("%d\n",ans);
}
参考文章:http://www.cnblogs.com/Lyush/p/3221503.html
最长回文子串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算法
回文串包括奇数长的和偶数长的,一般求的时候都要分情况讨论,这个算法做了个简单的处理把奇偶情况统一了.算法的基本思路是这样的,把原串每个字符中间用一个串中没出现过的字符分隔开来(统一奇偶),用一个数组p ...
随机推荐
- 什么是目标框架别名(What are the Target Framework Monikers (TFMs))?
我们现在的.NET Core 1.0应用(ASP.NET Core 1.0应用或控制台应用)有了新的被运行在不同框架上的可能性:①运行在.NET Core平台上 ②运行在传统的.NET Framewo ...
- linux下log4j乱码解决
使用log4j的时候,在WIN系统的时候正常显示中文,但是发布到linux系统的时候中文就显示成乱码了 由于log4j配置文件中没有设置编码格式(encoding),所以log4j就使用系统默认编码. ...
- 我的一个javascript项目的重构历程
一个月前,组内的一个内部使用的浏览器比价插件的前端部分交给我来维护,作为一个老司机我是拒绝的,自己的代码都是坑,还要去给别人填坑,搞笑地说. 呵呵,能拒绝么.... 好好享受吧,骚年...... 第一 ...
- 通过FTP连接Azure上的网站
下载发布文件 使用记事本(或其他文本工具)打开 找到ftp连接地址以及用户名.密码 使用ftp工具进行连接 输入相应参数,连接即可
- sudo gem install cocoapods 没反应问题
1. 尝试更新 sudo gem update --system 2. 查看安装详细 sudo gem install cocoapods -V 3.详细使用有个链接 http://blog.csdn ...
- Activity与Fragment的生命周期
今天看到一张图,详细描述了Activity和Fragment的生命周期,好资源共享咯!
- 解决Eclipse引用项目后乱码问题
1.将General-Workspace-Text file encoding 设置成UTF-82.导入项目,如果文件乱码,点文件右键Properties-Resource-Text file enc ...
- iOS设计模式之简单工厂模式
简单工厂模式 基本理解 到底要实例化谁,将来会不会增加实例化的对象,比如计算器增加开根运算,这是很容易变化的地方,应该考虑用一个单独的类来做这个创造实例的过程,这就是工厂. 通过使用工厂模式,我们可以 ...
- cell自适应高度
MyModel.h #import <Foundation/Foundation.h> #import <UIKit/UIKit.h> @interface MyModel : ...
- 简单认识UISwitch
以下是常用属性: self.mySwitch.layer.cornerRadius = 15; // 边框圆角角度 self.mySwitch.layer.borderWidth = 2; // ...