最长回文子串-LeetCode 5 Longest Palindromic Substring
题目描述
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.
即给定一个字符串,求它的最长回文子串的长度(或者最长回文子串)。
解法一
对于一个问题,一定可以找到一个傻的可爱的暴力解法,本题的暴力解法即:遍历整个字符串,以每一个字符为中心寻找以该字符为中心的最长回文子串,一次遍历下来即可获取最长回文子串,但是相应的这种方法的复杂度很糟糕O(N2)
这里值得注意的是要分开处理字符串长度为奇数或者偶数的情况
代码如下:
public String longestPalindrome(String s) {
String max = "";
int len = s.length();
for (int i = 0; i < len; i++) {
int odd = 0;
for (int j = 1; i + j < len && i >= j; j++) {
if (s.charAt(i + j) == s.charAt(i - j))
++odd;
else
break;
}
if (2 * odd + 1 > max.length())
max = s.substring(i - odd, i + odd + 1);
int even = 0;
for (int j = 1; i + j + 1 < len && i >= j; j++) {
if (s.charAt(i + j + 1) == s.charAt(i - j))
++even;
else
break;
}
if (even * 2 + 2 > max.length())
max = s.substring(i - even, i + even + 2 > s.length() ? s.length() : i + even + 2);
}
return max;
}
解法二
OK,笨的方法找到了,怎么样去提高效率。观察上面遍历的过程,对于字符串S,当以第i个字符为中心时,我们需要重新计算其最长回文子串,每个都是重头开始计算,那么能否利用回文字符串的性质来减少这种计算量从而提高整个算法的效率?答案是肯定的,下面要说的Manacher's 算法就是这样
统一奇偶
在正式开始算法之前,能否有一个方法将奇偶两种情况统一起来?为了达到这个目的,我们可以将原字符串S每个字符之间插入一个特殊字符'#',得到一个新的字符串T,如下
- S = "abaaba", T = "#a#b#a#a#b#a#".
这样可以发现无论长度奇偶都转换为奇情况来处理
Manacher算法
开头提到的思想,当我们要找寻以Tj为中心的回文子串时,能否利用前面已经算出的以Ti(i<j)为中心的回文子串,所以我们将前面算出的中间结果存入数组P,P[i]表示已Ti为中心的回文子串的长度(不包括其自身),而最长回文子串的长度就是P中的最大值。我们接着上面的例子

我们通过字符串T将对应的P写出,由于P6 = 6,可以很容易得出最长回文子串是"abaaba"
那么我们现在的关注点就主要放在如何计算P上,当然利用解法一那样我们可以通过遍历每一个点作为中心点来获取P,但是效率很低。还是前面提到的那个思想,当计算到第i个点作为中心点时,能否利用前面已经计算过的点。
观察回文串"abaaba"所对应的P,我们可以发现一条有用的规律,以i = 6作为中心,P中的数据时关于这个中心对称的,这不是偶然,我们可以尝试"aba",我们可以发现相似的对称性质。如果这条性质可以使用,我们就可以减少重复计算P的值。
为了验证这个思想,我们举一个稍微复杂一些的例子,S = "babcbabcbaccba",我们以图展现部分计算P的过程,从中找寻规律:

假设我们已经计算出一部分P的值,图中实线表示回文子串"abcbabcba"的中心位置,而虚线则表示该子串的左右边界
现在当我们想要计算i=13时P的值,已知i关于C的对称点i',我们怎样快速求出P[ i ]?
图中给出了我们的算法进行到i = 13的时候,我们需要计算P[ 13 ],我们来观察i关于回文子串中心点C的对称点i‘ = 9

图中我们用绿线标出了分别以i'和i为中心的回文子串,可以发现由于关于C点的对称性质,很容易得出P[ i ] = P[ i' ] = 1
通过以上分析,由于关于C的对称性质,我们很开心的得出一个结论P[ i ] = P[ i' ] = 1,而且之后的三个元素也都可以利用这条性质得出P的值(P[ 12 ] = P[ 10 ] = 0, P[ 13 ] = P[ 9 ] = 1, P[ 14 ] = P[ 8 ] = 0)

现在我们需要计算P[ 15 ],而i = 15关于C的对称点是i' = 7,那么p[ 15 ] = P[ 7 ] = 7?
当我们需要计算i = 15的时候,我们利用上面总结出的规律可以得出P[ 15 ] = P[ 7 ] = 7,但是进一步去计算P[ 15 ] 我们会发现以i = 15为中心点的最长回文子串是"a#b#c#b#a",事实是P[ 15 ] 要比对称点的子串短,这是为什么呢?

图中我们将以i'和以i为中心的子串用线标出,其中以绿线标出了严格根据中心点C对称的部分,而红线标出了超出
以C为中心点的子串的左右边界的部分,绿色的虚线部分标出了跨过中心点的部分
我们可以很清晰的发现,两个子串在绿色线标出的地方是完全对称的,同样绿色虚线部分由于中心对称也是满足的。然而P[ i' ] = 7,所以以i'为中心的子串超出了左边界,则这部分不再满足对称性质。我们只是知道P[ i ] ≥ 5,即i到右边界的长度。为了进一步得出P[ i ] 的值,我们需要向右扩展,在这里,由于P[ 21 ] ≠ P[ 7 ],所以P[ i ] = 5
我们总结一下上面发现的规律:
如果P[ i' ] ≤ R - i
那么 P[ i ] = P[ i' ]
否则 P[ i ] ≥ R - i (之后我们需要扩展出右边界来找到最终的P[ i ])
另外我们需要判断一下什么时候移动中心点C以及其右边界R
当以i为中心点的回文子串超出了右边界R时,我们将C移至i,将右边界R移至i的右边界
AC代码如下
private String insert(String s){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
sb.append('#');
sb.append(s.charAt(i));
}
sb.append('#');
return sb.toString();
}
public String longestPalindrome(String s) {
String t = insert(s);
int[] p = new int[t.length()];
int c = 0, r = 0; // 当前中心位置以及当前中心位置的右边界
for (int i = 0; i < t.length(); i++) {
int i_mirror = 2 * c - i;
p[i] = r > i ? Math.min(r - i, p[i_mirror]) : 0;
while (i + p[i] + 1 < t.length() && i - p[i] - 1 >= 0
&& t.charAt(i + p[i] + 1) == t.charAt(i - p[i] - 1))
p[i]++;
if (i + p[i] > r) {
c = i;
r = i + p[i];
}
}
int maxC = 0;
for (int i = 0; i < t.length(); i++) {
if (p[i] > p[maxC])
maxC = i;
}
return t.substring(maxC - p[maxC], maxC + p[maxC]).replace("#", "");
}
由于我们有两个变量中心点C以及右边界R,当P[ i ] ≤ R – i,我们直接以O(1)进行计算,而另一种情况则需要移动中心点和右边界,最多两者都是移动N步,所以总的时间负责度时O(2*N)即O(N)
——reference
Longest Palindromic Substring Part II
最长回文子串-LeetCode 5 Longest Palindromic Substring的更多相关文章
- 求最长回文子串 - leetcode 5. Longest Palindromic Substring
写在前面:忍不住吐槽几句今天上海的天气,次奥,鞋子里都能养鱼了...裤子也全湿了,衣服也全湿了,关键是这天气还打空调,只能瑟瑟发抖祈祷不要感冒了.... 前后切了一百零几道leetcode的题(sol ...
- 动态规划—最长回文子串LEETCODE第5题深度剖析
动态规划对于笔者来说有很重要的意义 一.题目如下: 对于此类题目,笔者常用的的办法是先做个暴力解题思路,然后再对暴力法进行优化. 二.暴力法 //字串遍历 public static String l ...
- Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)
Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...
- [LeetCode] 5. Longest Palindromic Substring 最长回文子串
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- 【LeetCode】5. Longest Palindromic Substring 最长回文子串
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:最长回文子串,题解,leetcode, 力扣,python ...
- LeetCode:Longest Palindromic Substring 最长回文子串
题目链接 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- leetcode 5 :Longest Palindromic Substring 找出最长回文子串
题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximum l ...
- [leetcode]5. Longest Palindromic Substring最长回文子串
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- [译+改]最长回文子串(Longest Palindromic Substring) Part II
[译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...
随机推荐
- 前端框架 EasyUI (1)熟悉一下EasyUI
jQuery EasyUI 官方网站 http://www.jeasyui.com/ .去年新开了个中文网 http://www.jeasyui.net/,不知道是不是官方的,不过看着挺像样.但是,广 ...
- TODO:macOS上ThinkPHP5和Semantic-UI集成
TODO:macOS上ThinkPHP5和Semantic-UI集成 1. 全局安装 (on OSX via homebrew)Composer 是 homebrew-php 项目的一部分 2. 把X ...
- Asp.net MVC 传递数据 从前台到后台,包括单个对象,多个对象,集合
今天为大家分享下 Asp.net MVC 将数据从前台传递到后台的几种方式. 环境:VS2013,MVC5.0框架 1.基本数据类型 我们常见有传递 int, string, bool, double ...
- 逆天Kali带你游遍大江南北~安全之前人铺路!
0.Linux基础学习(基本指令) http://www.cnblogs.com/dunitian/p/4822807.html 1.Kali安装到移动硬盘或者U盘中~Linux系列通用方法(包括An ...
- 04.LoT.UI 前后台通用框架分解系列之——轻巧的弹出框
LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...
- 使用etree.HTML的编码问题
title: 使用etree.HTML的编码问题 date: 2015-10-07 17:56:47 categories: [Python] tags: [Python, lxml, Xpath] ...
- 用scikit-learn学习DBSCAN聚类
在DBSCAN密度聚类算法中,我们对DBSCAN聚类算法的原理做了总结,本文就对如何用scikit-learn来学习DBSCAN聚类做一个总结,重点讲述参数的意义和需要调参的参数. 1. scikit ...
- 计算机程序的思维逻辑 (60) - 随机读写文件及其应用 - 实现一个简单的KV数据库
57节介绍了字节流, 58节介绍了字符流,它们都是以流的方式读写文件,流的方式有几个限制: 要么读,要么写,不能同时读和写 不能随机读写,只能从头读到尾,且不能重复读,虽然通过缓冲可以实现部分重读,但 ...
- ASP.NET Core 中文文档 第四章 MVC(4.6)Areas(区域)
原文:Areas 作者:Dhananjay Kumar 和 Rick Anderson 翻译:耿晓亮(Blue) 校对:许登洋(Seay) Areas 是 ASP.NET MVC 用来将相关功能组织成 ...
- 快速了解微信小程序的使用,一个根据小程序的框架开发的todos app
微信官方已经开放微信小程序的官方文档和开发者工具.前两天都是在看相关的新闻来了解小程序该如何开发,这两天官方的文档出来之后,赶紧翻看了几眼,重点了解了一下文档中框架与组件这两个部分,然后根据简易教程, ...