最长回文子串

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"
输出: "bb"

题目分析:

(1)暴力解法

首先容易想到暴力解法,可以找出字符串中所有的子串依次判断是否是回文串,此处采用一个稍微简化的方法,假设字符串中的各个字符都可以作为回文串的中心,分奇偶两种情况从各个位置向两侧拓展,利用一个max变量来记录遍历过程中出现过的最长的回文串的长度,用remi记录最长回文串的中心位置,复杂度为O()

代码如下:

class Solution {
public:
string longestPalindrome(string s) {
//从任一位置分成奇偶两种情况向左右遍历
int l = s.length();
int res = 1, remi = 0;
for(int i = 0; i < l; i++)
{
int j, k; //奇
j = k = i;
j--, k++;
while(j >= 0 && k < l)
{
if(s[j] != s[k]) break;
j--, k++;
}
if(res < k - j - 1) res = k - j - 1, remi = j + 1; //偶
j = k = i;
j--;
while(j >= 0 && k < l)
{
if(s[j] != s[k]) break;
j--, k++;
}
if(res < k - j - 1) res = k - j - 1, remi = j + 1;
}
string ans = s.substr(remi, res);
return ans;
}
};

(2)动态规划

暴力解法的原始思路是判断所有的子串是否是回文串,并从中选取最长的一个,此时有重叠子问题——对于一个在输入串中下标在[i, j] 的子串,其是回文串的必要条件是下标[i+1, j-1]的子串是回文串。

所以设dp[i][j] 为下标[i, j]的回文串长度,当子串为回文串时dp[i][j] = dp[i+1][j-1]+2,否则 dp[i][j] = 0

\[dp[i][j] = \begin{equation}
\left\{
\begin{array}{**lr**}
=dp[i+1][j-1]+2, &s[i] = s[j] \\
=0 & s[i] ≠ s[j]
\end{array}
\right.
\end{equation}
\]

需要在二维进行遍历,时间复杂度也为O()

代码如下:

class Solution {
public:
string longestPalindrome(string s) {
//动态规划,dp[i][j]表示以i开始到j所构成的回文子串长度,若不是回文串则为0,否则应为j-i+1
//dp[i][j] = dp[i+1][j-1]+2 (s[i] == s[j] && i+1到j-1构成回文串)
// 0 (s[i] != s[j] || i+1到j-1构不成回文串)
int l = s.length();
int ans = 1, remi = 0;
int dp[1005][1005];
for(int i = 0; i < l; i++)
{
dp[i][i] = 1;
}
for(int i = l - 1; i >= 0; i--)
{
for(int j = i+1; j < l; j++)
{
if(s[i] == s[j] && dp[i+1][j-1] == j - i - 1) dp[i][j] = dp[i+1][j-1] + 2;
else dp[i][j] = 0;
if(ans < dp[i][j]) ans = dp[i][j], remi = i;
}
}
string res = s.substr(remi, ans);
return res;
}
};

(3)Manacher算法

对于最长回文串问题,Manacher算法可以在O(n)的时间内解决。

Manacher算法通过插入分隔符将字符串长度设为奇数,然后求以各个字符为中心的回文串长度,以T[i]表示i点到其以自身为中心的回文串的最右端的距离(包含i点自身)。则最长回文子串即为T[i] max - 1

对T[i]的求法:

参考:https://subetter.com/algorithm/manacher-algorithm.html

利用回文串的对称性,利用mx记录到目前为止出现过的回文串可达的最右端,即最大的i+T[i],若i < mx,则说明当前的i作中心的回文串的某一部分已经在求其他T[i]时被扫描过,所以这一部分可以利用回文串的对称性快速求得,在一个回文串中,关于中心对称的位置的字符相同,不难想到完全被包含在某个回文串中的子回文串一定是以成对且子串中心关于整个回文串的中心对称。

所有不被包含在之前已经扫描过的回文串中的部分都需要依次判断,因此输出串的所有字符都被扫描过一次,时间复杂度为O(1)

代码如下:

class Solution {
public:
string longestPalindrome(string s) {
//Manacher算法
int l = s.length();
string str = "#";
for(int i = 0; i < l; i++)
{
str += s.substr(i, 1) + "#";
}
int p[2019];
l = l * 2 + 1;
int mx, id;
mx = id = 0;
for(int temp = 0; temp < l; temp++) p[temp] = 1;
int max = 0, remi = 0;
for(int i = 0; i < l; i++)
{
if(i < mx)
{
if(p[id*2-i] < mx - i) p[i] = p[id*2-i];
else p[i] = mx - i;
}
else p[i] = 1; int j = i + p[i];
while(j < l && 2 * i - j >= 0 && str[2*i-j] == str[j])
{
j++;
p[i]++;
}
if(mx < i + p[i]) mx = i + p[i], id = i;
if(max < p[i]) max = p[i], remi = i;
}
string ans = s.substr((remi-max+1)/2, max-1);
return ans;
}
};

(4)采用最长公共子串方法出现的错误

最初在看到问题时我首先想到了用最长公共子串的方法,将原字符串和其逆序字符串进行比对,求出最长公共子串,但是出现了问题,例如abcsdcba,求最长公共子串是abc,并不是回文串。如果对每个可能的子串再进行判断,则时间复杂度为O(n³)

LeetCode5 最长回文子串的更多相关文章

  1. leetcode-5 最长回文子串(动态规划)

    题目要求: * 给定字符串,求解最长回文子串 * 字符串最长为1000 * 存在独一无二的最长回文字符串 求解思路: * 回文字符串的子串也是回文,比如P[i,j](表示以i开始以j结束的子串)是回文 ...

  2. [Swift]LeetCode5. 最长回文子串 | Longest Palindromic Substring

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

  3. LeetCode5.最长回文子串 JavaScript

    给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab" 注意: &qu ...

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

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

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

    这算是一道经典的题目了,最长回文子串问题是在一个字符串中求得满足回文子串条件的最长的那一个.常见的解题方法有三种: (1)暴力枚举法,以每个元素为中心同时向左和向右出发,复杂度O(n^2): (2)动 ...

  6. lintcode最长回文子串(Manacher算法)

    题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ 最长回文子串 给出一个字符串 ...

  7. 1089 最长回文子串 V2(Manacher算法)

    1089 最长回文子串 V2(Manacher算法) 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 回文串是指aba.abba.cccbccc.aaaa ...

  8. 51nod1089(最长回文子串之manacher算法)

    题目链接: https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1089 题意:中文题诶~ 思路: 我前面做的那道回文子串的题 ...

  9. 求最长回文子串:Manacher算法

    主要学习自:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html 问题描述:回文字符串就是左右 ...

随机推荐

  1. IE8下不识别indexOf的问题

    1.为Array原型添加indexOf方法(如果学过面向对象,相当于给Array类添加实例方法),方法体如下: //添加数组IndexOf方法 if (!Array.prototype.indexOf ...

  2. windows系统PHP7开启curl_init

    1.php.ini,开启extension=php_curl.dll,去掉去掉前面的“;” 2.检查php.ini的extension_dir值是哪个目录(也就是插件扩展目录,比如php_curl.d ...

  3. 《LeetBook》leetcode题解(9):Palindrome Number[E]——回文数字

    我现在在做一个叫<leetbook>的开源书项目,把解题思路都同步更新到github上了,需要的同学可以去看看 地址:https://github.com/hk029/leetcode 这 ...

  4. mysql exceeded the 'max_questions' resource 记录

    最近Hive Meta的  Mysql 常报错 'user' has exceeded the 'max_questions' resource (current value: 10000) 解决:调 ...

  5. 快速排序分析及实现(C++)

    目录 快速排序算法分析及实现(C++) 算法思想 快速排序步骤 优点分析 C++语言实现 快速排序算法分析及实现(C++) 算法思想 ​ 把n个元素划分为三段:左端Left,中间段middle和右端r ...

  6. TCP网络参数优化

    TCP连接的状态 TCP连接过程是状态的转换,促使状态发生转换的因素包括用户调用.特定数据包以及超时等,具体状态如下所示: CLOSED:初始状态,表示没有任何连接. LISTEN:Server端的某 ...

  7. Git的常用撤销技巧与解决冲突方法

    git checkout . #本地所有修改的.没有的提交的,都返回到原来的状态 git stash #把所有没有提交的修改暂存到stash里面.可用git stash pop回复. git rese ...

  8. Java将Excel的列数以字母表示的字符串转换成数字表示

    我们知道,在 Excel 中,行数用数字表示,而列数是用字母表示的(如下图所示),有时候需要把它转换成数字来使用,或者把数字转换成字母.(例如使用POI操作Excel) 下面是转换代码,用来进行字母和 ...

  9. ios手势识别代理

    之前做优质派时写了个仿网易新闻导航的第三方,由于当时做项目时这个主控制器就是RootViewController,虽然用的是ScrollView但也没考虑到导航栏的手势返回的问题 ,现在做小区宝3.0 ...

  10. golang学习之接口型函数

    先说下使用接口型函数的好处: 1.不必将某个接口函数附在某个type上面,保证了命名随意 2. 可以直接调用函数或者使用该接口,两两不耽误 直接上代码吧: // interface_func proj ...