Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"

这道题让我们求最长回文子串,首先说下什么是回文串,就是正读反读都一样的字符串,比如 "bob", "level", "noon" 等等。那么最长回文子串就是在一个字符串中的那个最长的回文子串。LeetCode 中关于回文串的题共有五道,除了这道,其他的四道为 Palindrome NumberValidate PalindromePalindrome PartitioningPalindrome Partitioning II,我们知道传统的验证回文串的方法就是两个两个的对称验证是否相等,那么对于找回文字串的问题,就要以每一个字符为中心,像两边扩散来寻找回文串,这个算法的时间复杂度是 O(n*n),可以通过 OJ,就是要注意奇偶情况,由于回文串的长度可奇可偶,比如 "bob" 是奇数形式的回文,"noon" 就是偶数形式的回文,两种形式的回文都要搜索,对于奇数形式的,我们就从遍历到的位置为中心,向两边进行扩散,对于偶数情况,我们就把当前位置和下一个位置当作偶数行回文的最中间两个字符,然后向两边进行搜索,参见代码如下:

解法一:

class Solution {
public:
string longestPalindrome(string s) {
if (s.size() < ) return s;
int n = s.size(), maxLen = , start = ;
for (int i = ; i < n - ; ++i) {
searchPalindrome(s, i, i, start, maxLen);
searchPalindrome(s, i, i + , start, maxLen);
}
return s.substr(start, maxLen);
}
void searchPalindrome(string s, int left, int right, int& start, int& maxLen) {
while (left >= && right < s.size() && s[left] == s[right]) {
--left; ++right;
}
if (maxLen < right - left - ) {
start = left + ;
maxLen = right - left - ;
}
}
};

我们也可以不使用子函数,直接在一个函数中搞定,我们还是要定义两个变量 start 和 maxLen,分别表示最长回文子串的起点跟长度,在遍历s中的字符的时候,我们首先判断剩余的字符数是否小于等于 maxLen 的一半,是的话表明就算从当前到末尾到子串是半个回文串,那么整个回文串长度最多也就是 maxLen,既然 maxLen 无法再变长了,计算这些就没有意义,直接在当前位置 break 掉就行了。否则就要继续判断,我们用两个变量 left 和 right 分别指向当前位置,然后我们先要做的是向右遍历跳过重复项,这个操作很必要,比如对于 noon,i在第一个o的位置,如果我们以o为最中心往两边扩散,是无法得到长度为4的回文串的,只有先跳过重复,此时left指向第一个o,right指向第二个o,然后再向两边扩散。而对于 bob,i在第一个o的位置时,无法向右跳过重复,此时 left 和 right 同时指向o,再向两边扩散也是正确的,所以可以同时处理奇数和偶数的回文串,之后的操作就是更新 maxLen 和 start 了,跟上面的操作一样,参见代码如下:

解法二:

class Solution {
public:
string longestPalindrome(string s) {
if (s.size() < ) return s;
int n = s.size(), maxLen = , start = ;
for (int i = ; i < n;) {
if (n - i <= maxLen / ) break;
int left = i, right = i;
while (right < n - && s[right + ] == s[right]) ++right;
i = right + ;
while (right < n - && left > && s[right + ] == s[left - ]) {
++right; --left;
}
if (maxLen < right - left + ) {
maxLen = right - left + ;
start = left;
}
}
return s.substr(start, maxLen);
}
};

此题还可以用动态规划 Dynamic Programming 来解,根 Palindrome Partitioning II 的解法很类似,我们维护一个二维数组 dp,其中 dp[i][j] 表示字符串区间 [i, j] 是否为回文串,当 i = j 时,只有一个字符,肯定是回文串,如果 i = j + 1,说明是相邻字符,此时需要判断 s[i] 是否等于 s[j],如果i和j不相邻,即 i - j >= 2 时,除了判断 s[i] 和 s[j] 相等之外,dp[i + 1][j - 1] 若为真,就是回文串,通过以上分析,可以写出递推式如下:

dp[i, j] = 1                                               if i == j

= s[i] == s[j]                                if j = i + 1

= s[i] == s[j] && dp[i + 1][j - 1]    if j > i + 1

这里有个有趣的现象就是如果我把下面的代码中的二维数组由 int 改为 vector<vector<int>> 后,就会超时,这说明 int 型的二维数组访问执行速度完爆 std 的 vector 啊,所以以后尽可能的还是用最原始的数据类型吧。

解法三:

class Solution {
public:
string longestPalindrome(string s) {
if (s.empty()) return "";
int n = s.size(), dp[n][n] = {}, left = , len = ;
for (int i = ; i < n; ++i) {
dp[i][i] = ;
for (int j = ; j < i; ++j) {
dp[j][i] = (s[i] == s[j] && (i - j < || dp[j + ][i - ]));
if (dp[j][i] && len < i - j + ) {
len = i - j + ;
left = j;
}
}
}
return s.substr(left, len);
}
};

最后要来的就是大名鼎鼎的马拉车算法 Manacher's Algorithm,这个算法的神奇之处在于将时间复杂度提升到了 O(n) 这种逆天的地步,而算法本身也设计的很巧妙,很值得我们掌握,参见我另一篇专门介绍马拉车算法的博客 Manacher's Algorithm 马拉车算法,代码实现如下:

解法四:

class Solution {
public:
string longestPalindrome(string s) {
string t ="$#";
for (int i = ; i < s.size(); ++i) {
t += s[i];
t += '#';
}
int p[t.size()] = {}, id = , mx = , resId = , resMx = ;
for (int i = ; i < t.size(); ++i) {
p[i] = mx > i ? min(p[ * id - i], mx - i) : ;
while (t[i + p[i]] == t[i - p[i]]) ++p[i];
if (mx < i + p[i]) {
mx = i + p[i];
id = i;
}
if (resMx < p[i]) {
resMx = p[i];
resId = i;
}
}
return s.substr((resId - resMx) / , resMx - );
}
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/5

类似题目:

Shortest Palindrome

Palindrome Permutation

Palindrome Pairs

Longest Palindromic Subsequence

Palindromic Substrings

参考资料:

https://leetcode.com/problems/longest-palindromic-substring/

https://leetcode.com/problems/longest-palindromic-substring/discuss/2928/Very-simple-clean-java-solution

https://leetcode.com/problems/longest-palindromic-substring/discuss/2923/Simple-C%2B%2B-solution-(8ms-13-lines)

https://leetcode.com/problems/longest-palindromic-substring/discuss/2921/Share-my-Java-solution-using-dynamic-programming

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Longest Palindromic Substring 最长回文串的更多相关文章

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

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

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

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

  3. lintcode :Longest Palindromic Substring 最长回文子串

    题目 最长回文子串 给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串. 样例 给出字符串 "abcdzdcab",它的最长回文 ...

  4. Leetcode0005--Longest Palindromic Substring 最长回文串

    [转载请注明]http://www.cnblogs.com/igoslly/p/8726771.html 来看一下题目: Given a string s, find the longest pali ...

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

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

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

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

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

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

  8. 1. Longest Palindromic Substring ( 最长回文子串 )

    要求: Given a string S, find the longest palindromic substring in S. (从字符串 S 中最长回文子字符串.) 何为回文字符串? A pa ...

  9. 【翻译】Longest Palindromic Substring 最长回文子串

    原文地址: http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-i.html 转载请注明出处:http:// ...

随机推荐

  1. BFC的形成条件和特性分析

    初学CSS时,我们学到很多有意思的CSS规则,比如外边距塌陷,还有浮动元素的一些特性等,其实这些规则背后都是BFC这个东西在控制,下面我们来看下BFC到底是什么. 什么是BFC BFC(Block f ...

  2. [AngularJS] AngularJS系列(3) 中级篇之表单验证

    目录 基本验证 验证插件messages 自定义验证 基本验证 <form name="form" novalidate ng-app> <span>{{f ...

  3. ADO.NET存取数据库数据

    步骤: //数据库连接串 string conStr = "......" //创建连接对象 SqlConnection connection = new SqlConnectio ...

  4. 珍珠(bead)

    题目描述 有n颗形状和大小都一致的珍珠,它们的重量都不相同.n为整数,所有的珍珠从1到n编号.你的任务是发现哪颗珍珠的重量刚好处于正中间,即在所有珍珠的重量中,该珍珠的重量列(n+1)/2位.下面给出 ...

  5. Angular通过XHR加载模板而限制使用file://(解决方案)

    编写angular项目时,遇到此困难: angular.js:12011 XMLHttpRequest cannot load file:///E:/angular/imooc/chapter2/bo ...

  6. 关于css3的背景渐变

    关于css3的渐变,目前各大浏览器还未做到很好的支持,所以需要在我们使用时加上各大浏览器前缀. -moz-:使用Mozilla内核的浏览器(Firefox浏览器) -webkit-:使用Webkit内 ...

  7. dotnet core 使用 MongoDB 进行高性能Nosql数据库操作

    好久没有写过Blog, 每天看着开源的Java社区流口水, 心里满不是滋味. 终于等到了今年六月份 dotnet core 的正式发布, 看着dotnet 社区也一步一步走向繁荣, 一片蒸蒸日上的大好 ...

  8. 因为没用过,所以没想过的--goto

    今天读了读 Rui Maciel 大神写的 mjson parser,mjson 解析器是一个使用 ISO C 实现的小型 JSON 解析器.嵌入式项目中使用到了该解析器,随即拿出来看看. 看到如下代 ...

  9. 读《乔布斯的NeXT和苹果之间,隔了这两个创业常识》

    原文链接:http://wwww.huxiu.com/article/114950/1.html 前言: 当今硅谷风头最劲的风险投资家马克·安德森曾说,硅谷每年大约诞生15-20家真正值得投资的公司. ...

  10. Rocksdb引擎记录格式

    Rocksdb是一个kv引擎,由facebook团队基于levelDB改进而来,Rocksdb采用LSM-tree存储数据,良好的读写特性以及压缩特性使得其非常受欢迎.此外,Rocksdb引擎作为插件 ...