第五题:Longest Palindromic Substring

题目链接:题目链接

题意:找最长回文子串(注意不是回文序列,不一样,字串需要连续,序列不需要连续)

方法一:

这一题说实话,只想到最“土”的方法,就是找到所有的可能的串,然后得到最长的回文串。

需要注意:回文串有奇数和偶数之分,所以以当前这个点为中心,存在两种:这个点是最中间的点;这个点和之前一个点需要进行比较。

看代码如下:

class Solution {
public:
    string longestPalindrome(string s) {
        int max_len = 0, n = s.length(), len = 0, i, start = 0;
        int low, high;

        // 当前点参与回文比较
        //
        for (i = 0; i < n; ++i){
            low = i - 1;
            high = i;
            len = 0;
            while (low >= 0 && high < n && s[low] == s[high]){
                --low;
                ++high;
                len += 2;
            }
            if (max_len < len){
                start = low + 1;
                max_len = len;
            }
        }

        // 当前点不参与比较
        //
        for (i = 0; i < n; ++i){
            low = i - 1;
            high = i + 1;
            len = 1;
            while (low >= 0 && high < n && s[low] == s[high]){
                --low;
                ++high;
                len += 2;
            }
            if (max_len < len){
                start = low + 1;
                max_len = len;
            }
        }

        return s.substr(start, max_len);
    }
};

方法二:(网上学习得到)

这一题还有一个很有“技术”的算法,这个真的挺不错的!号称Manacher’s Algorithm,时间复杂度是O(n)。

1、首先这个算法建立在“奇数”数量字符字符串中才好使,所以第一步我们需要将原始的字符串改造成奇数个数,方法是,在所有字符之间个收尾都插入一个#字符,那么原来奇数的还是奇数,原来偶数的也是奇数个数了,例如:

aabb ==> #a#a#b#b#

aba ===> #a#b#a#

2、然后我们需要一个数组P记录以i字符为中心,向两边扩展最长的回文串。这个算法的优势在于什么呢?其实就是减少了一些位置处的回文串的计算。他借助的是回文串的对称性。例如:现在有一个回文串:

a  b  a  b  a  b  a  b  a

1  3  5  1  9  1  ?

根据前面的位置计算我们知道现在这个串是一个回文串,现在遍历到?位置,那么我们需要计算以?为中心(即a)的最长回文字符串是多少,一般情况我们是从?向左和向右进行遍历处理。但是存在一种情况是,如果前面(本例中中就是中间的a)是一个很大的回文字符串,?在这个串内,那么这个?可以不用计算就能得到结果,因为是和左边自己对称的a的值是一样的即5!所以不用遍历就知道答案是5!

a  b  a  b  a  b  a  b  a

所以这个算法其实就是钻了这个空子~~~

最终我们呢找到P数组中最大的值,就是所谓的以i为中心能扩张最大的回文串就是我们需要的结果。

下面具体说说本算法:

对于下面例子:

T =  #  a  #  b  #  a  #  a  #  b  #  a  # P =  0  1  0  3  0  1  6  1  0  3  0  1  0

首先我们呢需要知道,以最大值6为中心,这个值其实就是最大回文串长度,因为加入了相等长度的#,那么其实12/2=6就是咯~

那么P到底是怎么计算的呢?

我们看一个字符串:S = “babcbabcbaccba”.

如果现在我们遍历了的情况是下图:

(图片来自互联网)

C代表的是现在的中心点,L和R分别是以这个点为中心点扩展到两边最远的长度边界!

现在我们需要知道?处是什么答案,我们根据上面的理解,显然是以C为中心和?对称位置的值即9号位置,所以?=1。同理我们知道后面的# 和c处也是和前面一样对称的值!但是到了i=15处!!!有什么问题,看看:

(图片来自互联网)

可以知道对称位置7处,值是7,意思是以7为中心可以向两边扩展长度7。但是我们知道15处,不能扩展到7,只能扩展到5就结束了!这个是个关键处理!原因是什么呢?是由于i=15位置处如果想达到扩展7,必须要超过右边界R!!!而R之外的情况我们当前还是未知的!所以没有办法直接赋值对称位置较大的值7!现在只能赋值5!如果想扩展到7,只有向外扩展R,然后和左边进行比较!所以

P[i] = min(R-i, P[i对称值])

同时需要注意,如果R被扩展了,那么就需要更新,同时中心点C也被更新咯!

3、那么现在总结一下这个算法的步骤:

1)、如果当前位置在之前的那个中心范围内,即如果i<R,那么就可以使用对称性做,P[i] = min(R-i, P[对称值]);如果不在这个范围内,那么就是0为初值!!!

2)、然后看看能不能向当前已有的范围P[i]外面扩展,如果可以,那么++P[i]

3)、最后需要判断当前i为中心的右边界是不是已经超越之前的边界了,如果是,则需要更新右边界R和中心点C。

4)、最后,找到最大的P[i]就OK!

下面看代码:

class Solution {
public:
    string longestPalindrome(string s) {
        // 首先我们处理s字符串
		//
		string str = "^";
		int i = 0, n = s.length();
		while (i < n) {
			str += "#";
			str += s[i++];
		}
		// 结尾
		//
		str += "#$";

		// 下面正式处理
		//
		n = str.length();
		int *P = (int *)malloc(n*sizeof(int));
		memset(P, 0, n*sizeof(int));
		int C = 0, R = 0;

		for (i = 1; i < n - 1; ++i) {
			// 第一步,看看能不能取对称位置值
			// 对称位置:C-(i-C)=2-i
			//
			int symmetry_i = 2*C - i;	

			// 看看i在不在当前中心的回文范围内!
			// 如果在那么取min(R-i, P[symmetry_i]),
			// 否则初始化为0
			//
			P[i] = R > i ? min(R-i, P[symmetry_i]) : 0;

			// 下面看看以i为中心,在P[i]之外还能不能扩展
			//
			while (str[i + P[i] + 1] == str[i - P[i] - 1])
				++P[i];

			// 最后看看扩展的范围是不是超过R边界了
			// 如果超过了,需要处理C和R
			//
			if (P[i] + i > R){
				R = P[i] + i;
				C = i;
			}
		}

		// 找到最大的P[i]值
		//
		int idx = 0;
		int max_len = 0;
		for (i = 0; i < n; ++i) {
			if (P[i] > max_len){
				idx = i;
				max_len = P[i];
			}
		}

		// 返回这个找到的字符串,注意使用的是原始字符串s哦!
		//
		return s.substr((idx - max_len - 1)/2, max_len);
    }
};
时间: 2024-08-06 04:58:42

第五题:Longest Palindromic Substring的相关文章

leetcode第五题--Longest Palindromic Substring

Problem: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. 找出最大的回文子串,回文就是指字符串倒过来和之前的一样.例如aba  倒过来还是aba.abac中的最大回文子串就是aba. 我一开始

Leetcode第五题_Longest Palindromic Substring

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. Leetcode第5题,题目大概意思是给一个字符串,从中找出最长的回文串,所谓回文串,就是

LeetCode第五题,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. 题意解析: 最长回文子串.就是给定一个字符串S,找出其中的最长回文子串,并返回该子串. 解法: 第一种方法显然是循环暴力枚举,复杂度为O(

LeetCode第[5]题(Java):Longest Palindromic Substring 标签:String、动态规划

题目中文:求最长回文子串 题目难度:Medium 题目内容: Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. 翻译: 给定一个字符串s,找出s中最长的回文子串.你可以假设s的最大长度是1000. 什么叫回文子串? 就是字符串中,满足能正读反读都一样的子串,就是回文子串.如下所示 Input: "babad"

刷题5. Longest Palindromic Substring

一.题目说明 Longest Palindromic Substring,求字符串中的最长的回文. Difficuty是Medium 二.我的实现 经过前面4个题目,我对边界考虑越来越"完善"了. 总共提交了5次: 第1.2次:Wrong Answer 主要是"cbbd"错误了,重复的判断逻辑上出了点小问题 第3.4次: Time Limit Exceeded 我本地代码运行没问题的,但是提交后,报错.给了一个超长的用例: 321012321001232100123

LeetCode(4) || Longest Palindromic Substring 与 Manacher 线性算法

LeetCode(4) || Longest Palindromic Substring 与 Manacher 线性算法 题记 本文是LeetCode题库的第五题,没想到做这些题的速度会这么慢,工作之余全部耗在这上面了,只怪自己基础差.本文主要介绍使用Manacher线性算法来求解字符串的最长回文子字符串. 题目 Given a string S, find the longest palindromic substring in S. You may assume that the maxim

LeetCode OJ: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. 玩了两天dota2,罪过罪过,还是应该老老实实刷题啊. 题目求得是最长的回文子串,这里使用的是暴力的解法,也就是解决两种回文"asdsa"以

LeetCode #5 Longest Palindromic Substring (M)

[Problem] 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. [Analysis] 这题的思路有很多种,网上也有各种讨论.这里我采用的是个人觉得比较好理解的一种利用Dynamic Progra

LeetCode 005 Longest Palindromic Substring - Java

Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. Example: Input: "babad" Output: "bab" Note: "aba" is also a valid answer. Example: Input: "cbbd" Ou

[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. 求字符串中的最大回文子串(从左往右和从右往左读一样的子串). Example: Input: "babad" Output: "bab" Note: "aba" is also a valid answer. Exam