题目描述

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的更多相关文章

  1. 求最长回文子串 - leetcode 5. Longest Palindromic Substring

    写在前面:忍不住吐槽几句今天上海的天气,次奥,鞋子里都能养鱼了...裤子也全湿了,衣服也全湿了,关键是这天气还打空调,只能瑟瑟发抖祈祷不要感冒了.... 前后切了一百零几道leetcode的题(sol ...

  2. 动态规划—最长回文子串LEETCODE第5题深度剖析

    动态规划对于笔者来说有很重要的意义 一.题目如下: 对于此类题目,笔者常用的的办法是先做个暴力解题思路,然后再对暴力法进行优化. 二.暴力法 //字串遍历 public static String l ...

  3. Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)

    Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...

  4. [LeetCode] 5. Longest Palindromic Substring 最长回文子串

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  5. 【LeetCode】5. Longest Palindromic Substring 最长回文子串

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:最长回文子串,题解,leetcode, 力扣,python ...

  6. LeetCode:Longest Palindromic Substring 最长回文子串

    题目链接 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  7. leetcode 5 :Longest Palindromic Substring 找出最长回文子串

    题目: Given a string S, find the longest palindromic substring in S. You may assume that the maximum l ...

  8. [leetcode]5. Longest Palindromic Substring最长回文子串

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  9. [译+改]最长回文子串(Longest Palindromic Substring) Part II

    [译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...

随机推荐

  1. Database Replay和Consolidated Database replay

    简介 在数据库的迁移和升级场景中,我们经常会遇到一个问题:在做压力测试时,如何模拟真实的业务压力,解决这个问题的方法有很多,比如:应用方开发模拟程序或者使用压力测试工具模拟,如load runner, ...

  2. 【开源】简单4步搞定QQ登录,无需什么代码功底【无语言界限】

    说17号发超简单的教程就17号,qq核审通过后就封装了这个,现在放出来~~ 这个是我封装的一个开源项目:https://github.com/dunitian/LoTQQLogin ————————— ...

  3. 在 Laravel 中使用图片处理库 Integration/Image

    系统需求 PHP >= 5.3 Fileinfo Extension GD Library (>=2.0) … or … Imagick PHP extension (>=6.5.7 ...

  4. H5坦克大战之【玩家控制坦克移动2】

    周一没有看圣诞大战,这几天比较忙也没有看赛后的报道,今天就先不扯NBA,随便扯扯自己.昨天在电脑里找东西的时候翻到以前兼职健身教练时的照片,思绪一下子回到学生时代,脑子久久换不过来.现在深深觉得健身和 ...

  5. Drawable实战解析:Android XML shape 标签使用详解(apk瘦身,减少内存好帮手)

    Android XML shape 标签使用详解   一个android开发者肯定懂得使用 xml 定义一个 Drawable,比如定义一个 rect 或者 circle 作为一个 View 的背景. ...

  6. BPM配置故事之案例9-根据表单数据调整审批线路2

    老李:好久不见啊,小明. 小明:-- 老李:不少部门有物资着急使用,现在的审批流程太慢了,申请时增加一个是否加急的选项吧.如果选加急,金额1000以下的直接到我这里,我审批完就通过,超过1000的直接 ...

  7. sqlyog导出json数据格式支持mysql数据转存mongodb

    <!-------------知识的力量是无限的(当然肯定还有更简单的方法)-----------!> 当我考虑将省市区三级联动数据从mysql转入mongodb时遇到了网上无直接插入mo ...

  8. Autofac 的点滴

    泛型类型的注册和使用 public interface IRepository<T> where T:class { } public interface ISchoolDetailRep ...

  9. click事件的累加绑定,绑定一次点击事件,执行多次

    最近做项目为一个添加按钮绑定点击事件,很简单的一个事情,于是我按照通常做法找到元素,使用jquery的on()方法为元素绑定了点击事件,点击同时发送请求.完成后看效果,第一次点击没有问题.再一次点击后 ...

  10. Nova PhoneGap框架 第一章 前言

    Nova PhoneGap Framework诞生于2012年11月,从第一个版本的发布到现在,这个框架经历了多个项目的考验.一直以来我们也持续更新这个框架,使其不断完善.到现在,这个框架已比较稳定了 ...